技术开发 频道

ADO.NET实现应用程序数据访问层

规则5:抽象化.NET Framework data provider

  最后一个规则指定,为什么应该对在DAL内部使用的.NET Framework data provider抽象化,以及应该如何进行抽象。正如我已经提到的那样,ADO.NET编程模型公开了独特的.NET Framework data provider,包括SqlClient、OleDb和其他可从 MSDN 在线Web站点上获得的data provider。尽管该设计能够提高性能,并且使provider能够公开特定于数据源的功能(例如SqlCommand对象的ExecuteXMLReader方法),但它会迫使开发人员决定针对哪个provider进行编码。换句话说,开发人员通常选择使用SqlClient或OleDb,然后直接针对各个命名空间中的类编写代码。

public enum ProviderType : int {SqlClient = 0, OLEDB = 1} public class ProviderFactory {  public ProviderFactory(ProviderType provider) {   _pType = provider;   _initClass();  }  public ProviderFactory() {   _initClass();  }  private ProviderType _pType = ProviderType.SqlClient;  private bool _pTypeSet = false;  private Type[] _conType, _comType, _parmType, _daType;  private void _initClass() {   _conType = new Type[2];   _comType = new Type[2];   _parmType = new Type[2];   _daType = new Type[2];   // Initialize the types for the providers   _conType[(int)ProviderType.SqlClient] = typeof(SqlConnection);   _conType[(int)ProviderType.OLEDB] = typeof(OleDbConnection);   _comType[(int)ProviderType.SqlClient] = typeof(SqlCommand);   _comType[(int)ProviderType.OLEDB] = typeof(OleDbCommand);   _parmType[(int)ProviderType.SqlClient] = typeof(SqlParameter);   _parmType[(int)ProviderType.OLEDB] = typeof(OleDbParameter);   _daType[(int)ProviderType.SqlClient] = typeof(SqlDataAdapter);   _daType[(int)ProviderType.OLEDB] = typeof(OleDbDataAdapter);  }  public ProviderType Provider {   get {    return _pType;   }   set {    if (_pTypeSet) {     throw new ReadOnlyException_ ("Provider already set to " + _pType.ToString());    }    else {     _pType = value;     _pTypeSet = true;    }   }  }  public IDataAdapter CreateDataAdapter_ (string commandText,IDbConnection connection) {   IDataAdapter d;   IDbDataAdapter da;   d = (IDataAdapter)Activator.CreateInstance_ (_daType[(int)_pType], false);   da = (IDbDataAdapter)d;   da.SelectCommand = this.CreateCommand(commandText, connection);   return d;  }  public IDataParameter CreateParameter_ (string paramName, DbType paramType) {   IDataParameter p;   p = (IDataParameter)Activator.CreateInstance_ (_parmType[(int)_pType], false);   p.ParameterName = paramName;   p.DbType = paramType;   return p;  }  public IDataParameter CreateParameter_ (string paramName, DbType paramType, Object value) {   IDataParameter p;   p = (IDataParameter)Activator.CreateInstance_ (_parmType[(int)_pType], false);   p.ParameterName = paramName;   p.DbType = paramType;   p.Value = value;   return p;  }  public IDbConnection CreateConnection(string connect) {   IDbConnection c;   c = (IDbConnection)Activator.CreateInstance_ (_conType[(int)_pType], false);   c.ConnectionString = connect;   return c;  }  public IDbCommand CreateCommand(string cmdText,_ IDbConnection connection) {   IDbCommand c;   c = (IDbCommand)Activator.CreateInstance_ (_comType[(int)_pType], false);   c.CommandText = cmdText;   c.Connection = connection;   return c;  } }
  如果您要更改.NET Framework data provider,则需要重新编写数据访问方法的代码。为了避免这种情况,可以使用称为抽象工厂(Abstrace Factory)的设计模式。使用该模式,可以生成一个简单的类,该类将公开能够基于标识传入到构造函数的.NET Framework data provider的信息来创建主要的.NET Framework data provider对象(命令、连接、数据适配器和参数)的方法。图7中的代码显示了该类的一个简化的C#版本。为了使用该类,数据访问类中的代码需要针对.NET Framework data provider实现的各种接口(包括IDbCommand、IDbConnection、IDataAdapter和IDataParameter)进行编程。例如,为了用来自参数化存储过程的结果填充DataSet,您可以在数据访问类的方法内部使用以下代码:
Dim _pf As New ProviderFactory(ProviderType.SqlClient) Dim cn As IDbConnection = _pf.CreateConnection(_connect) Dim da As IDataAdapter = _pf.CreateDataAdapter("usp_GetBook", cn) Dim db As IDbDataAdapter = CType(da, IDbDataAdapter) db.SelectCommand.CommandType = CommandType.StoredProcedure db.SelectCommand.Parameters.Add(_pf.CreateParameter("@productId", _ DbType.Int32, id)) Dim ds As New DataSet("Books") da.Fill(ds)
  通常,您需要在类级别声明ProviderFactory变量,并且在数据访问类的构造函数中将其实例化。另外,就像这里显示的那样,它的构造函数将用从配置文件中读取的data provider填充,而不是硬编码。如您想像的那样,将ProviderFactory添加到DAL基类中会非常美妙,然后可以将它包含在程序集中并分发给其他开发人员。您还可以更深入一步,以封装开发人员反复编写的常见ADO.NET代码。
 
小结
 
  身处于Web Service时代之中,我们会构建越来越多的应用程序从独立的应用层来操纵数据。如果您遵循某些基本规则并最终将其作为一种习惯,那么编写数据访问代码会变得更快、更容易并且代码也会具有更高的可重用性,从而节省了与服务器之间的交互并使您在代码中保持数据的独立。
0
相关文章