数据访问层的抽象工厂模式实现

在软件开发中,数据访问层(DAL)是一个至关重要的部分,它负责应用程序与数据库之间的交互。随着应用程序的复杂度增加,数据访问层的实现也变得越来越复杂。为了简化这一过程,可以使用抽象工厂模式来创建一个灵活且可扩展的数据访问层。

System.Data命名空间主要由构成ADO.NET架构的类组成,它还定义了一系列数据访问接口,这些接口可以被不同的数据提供者使用。理想情况下,希望能够有一个数据访问层组件,它既可以用于开发时的Access 2000数据库,也可以用于生产环境中的SQL Server或Oracle数据库。

抽象工厂模式

为了实现这一目标,引入了里氏替换原则(Liskov Substitution Principle),它指出派生类必须能够通过基类接口使用,而不需要用户知道具体的差异。换句话说,实现了接口的类的实例可以被向上转型为接口类型。这有助于理解一个非常有用的模式——抽象工厂模式。

抽象工厂设计模式提供了一个创建相关或依赖对象家族的契约,而不需要指定它们的具体类。

抽象工厂模式涉及以下角色:

  • 抽象工厂(AbstractFactory)
  • 具体工厂(ConcreteFactory)
  • 抽象产品(AbstractProduct)
  • 具体产品(ConcreteProduct)
  • 客户端(Client)

使用抽象工厂模式有以下后果:

  • 隔离具体类
  • 便于交换产品家族
  • 促进产品间的一致性
  • 支持新产品种类可能比较困难

实现

抽象工厂通常是单例的,通常使用工厂方法来创建产品。需要创建数据访问层对象,但也需要系统独立于每个DAL的创建方式。以下代码块显示了代表抽象产品的IDal接口。

public interface IDal { IDbCommand CreateCommand(); IDbCommand CreateCommand(string cmdText); IDbCommand CreateCommand(string cmdText, IDbConnection cn); IDbCommand CreateCommand(string cmdText, IDbConnection cn, IDbTransaction trans); IDbConnection CreateConnection(); IDbConnection CreateConnection(string cnString); IDbDataAdapter CreateDataAdapter(); IDbDataAdapter CreateDataAdapter(IDbCommand selectCmd); IDbDataAdapter CreateDataAdapter(string selectCmdText, string selectCnString); IDbDataAdapter CreateDataAdapter(string selectCmdText, IDbConnection selectCn); IDataReader CreateDataReader(IDbCommand dbCmd); IDataReader CreateDataReader(IDbCommand dbCmd, CommandBehavior dbCmdBehavior); }

实现示例

为了使输入/输出参数独立于实现,使用了公共接口(System.Data)作为参数类型。现在是时候实现扩展IDAL接口的实际产品了。为此,需要创建一个新类,将称之为OracleDal。为什么叫OracleDal?因为想构建一个Oracle访问点。当然,可以看到附上的完整源代码,并点击其他图标,可以使用许多其他提供者创建不同的对象。以下示例显示了一个简化的OracleDal实现。

public class OracleDal : IDal { public IDbCommand CreateCommand(string cmdText, IDbConnection cn, IDbTransaction trans) { IDbCommand oracleCmd = null; try { oracleCmd = new OracleCommand(cmdText, (OracleConnection)cn, (OracleTransaction)trans); } catch (OracleException oracleExc) { if (oracleCmd != null) oracleCmd.Dispose(); throw new Exception(oracleExc.Message); } return oracleCmd; } public IDataReader CreateDataReader(IDbCommand dbCmd, CommandBehavior dbCmddBehavior) { IDataReader dr = null; try { dr = dbCmd.ExecuteReader(dbCmddBehavior); } catch (OracleException oracleExc) { if (dr != null) { if (!dr.IsClosed) dr.Close(); dr.Dispose(); } throw new Exception(oracleExc.Message); } return dr; } public IDbConnection CreateConnection(string cnString) { IDbConnection oracleCn = null; try { oracleCn = new OracleConnection(cnString); } catch (OracleException oracleExc) { if (oracleCn != null) oracleCn.Dispose(); throw new Exception(oracleExc.Message); } return oracleCn; } public IDbDataAdapter CreateDataAdapter(string selectCmdText, IDbConnection selectCn) { IDbDataAdapter oracleDataAdapter = null; try { oracleDataAdapter = new OracleDataAdapter(selectCmdText, (OracleConnection)selectCn); } catch (OracleException oracleExc) { throw new Exception(oracleExc.Message); } return oracleDataAdapter; } }

其他数据库实现

public class DB2Dal : IDal { public IDbCommand CreateCommand(string cmdText, IDbConnection cn, IDbTransaction trans) { IDbCommand db2Cmd = null; try { db2Cmd = new iDB2Command(cmdText, (db2Connection)cn, (iDB2Transaction)trans); } catch (iDB2Exception db2Exc) { if (db2Cmd != null) db2Cmd.Dispose(); throw new Exception(db2Exc.Message); } return db2Cmd; } public IDataReader CreateDataReader(IDbCommand dbCmd, CommandBehavior dbCmddBehavior) { IDataReader dr = null; try { dr = dbCmd.ExecuteReader(dbCmddBehavior); } catch (iDB2Exception db2Exc) { if (dr != null) { if (!dr.IsClosed) dr.Close(); dr.Dispose(); } throw new Exception(db2Exc.Message); } return dr; } public IDbConnection CreateConnection(string cnString) { IDbConnection db2Cn = null; try { db2Cn = new iDB2Connection(cnString); } catch (iDB2Exception db2Exc) { if (db2Cn != null) db2Cn.Dispose(); throw new Exception(db2Exc.Message); } return db2Cn; } public IDbDataAdapter CreateDataAdapter(string selectCmdText, IDbConnection selectCn) { IDbDataAdapter db2DataAdapter = null; try { db2DataAdapter = new iDB2DataAdapter(selectCmdText, (iDB2Connection)selectCn); } catch (iDB2Exception db2Exc) { throw new Exception(db2Exc.Message); } return db2DataAdapter; } } public class SqlDal : IDal { public IDbCommand CreateCommand(string cmdText, IDbConnection cn, IDbTransaction trans) { IDbCommand sqlCmd = null; try { sqlCmd = new SqlCommand(cmdText, (SqlConnection)cn, (SqlTransaction)trans); } catch (SqlException sqlExc) { if (sqlCmd != null) sqlCmd.Dispose(); throw new Exception(sqlExc.Message); } return sqlCmd; } public IDataReader CreateDataReader(IDbCommand dbCmd, CommandBehavior dbCmddBehavior) { IDataReader dr = null; try { dr = dbCmd.ExecuteReader(dbCmddBehavior); } catch (SqlException sqlExc) { if (dr != null) { if (!dr.IsClosed) dr.Close(); dr.Dispose(); } throw new Exception(sqlExc.Message); } return dr; } public IDbConnection CreateConnection(string cnString) { IDbConnection sqlCn = null; try { sqlCn = new SqlConnection(cnString); } catch (SqlException sqlExc) { if (sqlCn != null) sqlCn.Dispose(); throw new Exception(sqlExc.Message); } return sqlCn; } public IDbDataAdapter CreateDataAdapter(string selectCmdText, IDbConnection selectCn) { IDbDataAdapter sqlDataAdapter = null; try { sqlDataAdapter = new SqlDataAdapter(selectCmdText, (SqlConnection)selectCn); } catch (SqlException sqlExc) { throw new Exception(sqlExc.Message); } return sqlDataAdapter; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485