独立数据访问层( 文档进行中)






4.83/5 (114投票s)
通过更改标志在数据库之间切换的艺术

引言
开发人员经常编写使用数据库的应用程序。由于这是非常普遍的,因此他们需要简化与数据访问功能相关的任务。应用程序通常需要根据每个数据库的编程模型进行调整。
背景
System.Data
命名空间
主要包含构成 ADO.NET 体系结构的类。这个命名空间
还定义了许多可以被不同提供者使用的数据访问接口。拥有一个在开发中可用于 Access 2000 数据库,在生产环境中可用于 SQL Server 或 Oracle 数据库的数据访问层组件,应该是一个梦想。难道不是吗?
我是如何考虑这样做的?
Liskov 替换原则可以帮助我们。它指出,派生类必须可以通过基类接口使用,而无需用户知道差异。简单来说,这意味着实现接口的类的对象可以被向上转换为接口类型。我引入这一点是因为它可以帮助我们理解一个非常有用的模式,称为抽象工厂。抽象工厂模式的目的是什么?
抽象工厂类图
抽象工厂设计模式提供了创建相关或依赖对象族的契约,而无需指定它们的具体类。
- 参与者和协作者
AbstractFactory (抽象工厂)
ConcreteFactory
ConcreteProduct (具体产品)
AbstractProduct (抽象产品)
客户端
- 后果
- 隔离具体类
- 轻松交换产品族
- 促进产品之间的一致性
- 添加新类型产品可能很困难
- 实现
- 抽象工厂通常是单例模式
- 通常,工厂方法用于创建产品
数据访问层接口
我们需要创建数据访问层对象,但我们也需要系统独立于每个 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
实现。
Oracle
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( dbCmdBehavior );
}
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;
}
}
DB2
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( dbCmdBehavior );
}
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;
}
}
SQL Server
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( dbCmdBehavior );
}
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;
}
}
信息
本文的描述不完整。对此我感到抱歉。我将尽快插入其余部分。如果您愿意,可以使用我附带的完整源代码。如果您有任何建议,请与我联系。