使用反射+抽象工厂的数据访问(1)


应用程序有时需要适应于不同的数据库,例如要将一个 Access 数据库的网站改成使用 Sql Server 数据库。由于 SQL Server 和 Access 在 ADO.Net 上的使用是不同的, SQL Server 使用的是 System.Data.SqlClient 命名空间下的 SqlConnection 、 SqlCommand 、 SqlParameter 、 SqlDataReader 、 SqlDataAdapter ,而 Access 则使用的是 System.Data.Oledb 命名空间下的相应的类。所以需要大量的查找、替换工作,这不是一个聪明的方式。如何使用软件设计模式,以不变应万变,保证代码的修改量是最小的呢?最基本的思想就是:将相同部分的代码提取出来,做成单独的类或接口,通过增加层次来提高代码的重用性。
例如,对于 Access 和 SQL Server ,都需要使用一段类似的代码来创建数据库的连接。
Access 的格式
using System;
using System.Data;
using  System.Data.Oledb;

private  OledbConnection conn;
private void OpenConnection()
{
        string strConnection;
conn=new  System.Data.Oledb.OledbConnection(strConnection)
}
 
Sql Server  的格式
 
using System;
using System.Data;
using  System.Data.Oledb;

private  OledbConnection conn;
private void OpenConnection()
{
        string strConnection;
conn=new  System.Data.Oledb.OledbConnection(strConnection)
}
 
注意:除了上面黑体部分不同之外,其他代码都一模一样。如果能将这些黑体文字替换成一种对于 Access 、 Sql Server 都通用的 Connection 对象,具体使用什么数据库,系统只需要作一个简单设置,如通过 Web.Config 设置或定义一个字符串指定数据库的类型,那多方便啊。
 
抽象工厂模式(Abstract Factory Pattern )简介
抽象工厂模式有下面的一些优点和缺点:
1)  它分离了具体的类。 Abstract Factory 模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离。客户通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。
2)  它使得易于交换产品系列一个具体工厂类在一个应用中仅出现一次―即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。在我们的用户界面的例子中,我们仅需转换到相应的工厂对象并重新创建接口,就可实现从 M o t i f 窗口组件转换为 Presentation Manager 窗口组件。
3)  它有利于产品的一致性当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而 A b s t r a c t F a c t o r y 很容易实现这一点。
4)  难以支持新种类的产品难以扩展抽象工厂以生产新种类的产品。这是因为 A b s t r a c t F a c t o r y 接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及 A b s t r a c t F a c t o r y 类及其所有子类的改变。
具体代码实现
1 、定义抽象工厂类(DbProviderFactories.cs )。
抽象工厂类需要返回多个具体类(多种数据库)中的一个。所以 GetFactory() 返回的类型是一个具体的工厂类
 
using System;
using System.Web;
using System.Configuration;
using System.Data;
using System.Data.Common;
using Microsoft.Win32;
 
namespace SplendidCRM
{
        /// <summary>
        /// Summary description for DbProviderFactories.
        /// </summary>
        public class DbProviderFactories
        {
               public static  DbProviderFactory  GetFactory()
               {
                      //  从 Application 中获取信息
HttpApplicationState Application = HttpContext.Current.Application;
                      string sSplendidProvider = Sql.ToString(Application["SplendidProvider"]);
                      string sConnectionString = Sql.ToString(Application["ConnectionString"]);
                      //  如果在 Application 没有信息,则从 Web.Config 中获取。
/*
<configuration>
   <appSettings>
     <add key="SplendidProvider" value="System.Data.SqlClient" />
     <add key="SplendidSQLServer" value="Password=123;User ID=sa;Initial Catalog=DB;Data Source=WWW;Packet Size=4096" />
   </appSettings>
*/
                      if ( Sql.IsEmptyString(sSplendidProvider) || Sql.IsEmptyString(sConnectionString) )
                      {
                             sSplendidProvider = ConfigurationSettings.AppSettings["SplendidProvider"];
                             switch ( sSplendidProvider )
                             {
                                    case "System.Data.SqlClient":
                                            sConnectionString = ConfigurationSettings.AppSettings["SplendidSQLServer"];
                                           break;
                                    case "System.Data.OracleClient":
                                           sConnectionString = ConfigurationSettings.AppSettings["SplendidSystemOracle"];
                                           break;
                                    case "Oracle.DataAccess.Client":
                                           sConnectionString = ConfigurationSettings.AppSettings["SplendidOracle"];
                                           break;
                             }
                             Application["SplendidProvider"] = sSplendidProvider;
                             Application["ConnectionString"] = sConnectionString;
                      }
                      return GetFactory(sSplendidProvider, sConnectionString);
               }
      
               ///
               public static  DbProviderFactory  GetFactory(string sSplendidProvider, string sConnectionString)
               {
                      switch ( sSplendidProvider )
                      {
                             case "System.Data.SqlClient":
                             {
                                    return new SqlClientFactory(sConnectionString);
                             }
                             case "System.Data.OracleClient":
                             {
                                    return new OracleSystemDataFactory(sConnectionString);
                             }
                             case "Oracle.DataAccess.Client":
                             {
                                    return new OracleClientFactory(sConnectionString);
                             }
                             default:
                                    throw(new Exception(" 不支持的 factory " + sSplendidProvider));
                      }
               }
        }
}
 


你可能感兴趣的:(使用反射+抽象工厂的数据访问(1))