首页 > 代码库 > 比较好的三层的理解(转载)---基于工厂模式

比较好的三层的理解(转载)---基于工厂模式

在项目开发时,有时候可能会增加或修改新的数据库,比如,刚开始我们项目用SQL Server 数据库,但后来需要用Oracle 数据库,或者说在某些情况下需要用Oracle 来代替SQL Server 数据库,甚至两种情况会同时存在,但数据库访问方面 Oracle 和SQL Server 是不同的,它们的语句写法不同,甚至所示哟哦那个的.NET Framework  数据提供程序也是不同的,那应该怎么办呢?

1. 新增数据访问层

我们不修改原来的DAL的代码,可以将原来的项目命名为SQLServerDAL,我们可以增加一个针对Oracle的DAL项目来单独实现对Oracle的访问。这样就会有两个DAL,一个用于访问SQLServer,一个用于访问Oracle。

2. 实现IDAL抽象接口

由于SQL Server 和 Oracle 对数据库的基本操作是一样的,都是增、删、改、查。所以,可以将相同的功能的操作的一系列对象抽象出来实现同一个接口:IDAL。让SQLServerDAL  的类 和OracleDAL 的类都继承这个接口。具体方法如下:

(1)添加IDAL类库项目和接口文件IManager.cs,具体代码如下(由于接口中调用Model, 所以需要添加对Model项目的引用)

//IManager.cs

namespace IDAL
{
   /// <summary>
   /// 接口层IManager的摘要说明
   /// </summary>
    public interface IManager
    {
        //<summary>
        //增加一条数据
        //</summary>
        int Add(Model.Manager model);  
        //<summary>
        //更新一条数据
        //</summary>
        void Update(Model.Manager model);
        //<summary>
        //删除一条数据
        //</summary>
        void Delete(string managerid);
        //<summary>
        //得到一个实体
        //</summary>
        Hui.Model.Manager GetModel(string managerid);
        //<summary>
        //获得数据列表
        //</summary>
        DataSet GetList(string managerid);
    }

(2)在SQLServerDAL 和 OracleDAL 项目中添加对IDAL项目的引用,然后,SQLServerDAL 和 OracleDAL 项目中分别创建一个数据访问类:Manager,并继承自IManager的接口。

//SQLServerDAL.cs

using System.Data;
using System.Data.SqlClient;
using DBUtility;
using IDAL;
namespace SQLServerDAL
{
    /// <summary>
    /// Manager 数据访问类
    /// </summary>
    public class Manager:IManager
    {
        public Manager()
        { 
        }
        //<summary>
        //增加一条记录
        //</summary>
        public int Add(Model.Manager manager)
        {
            return 0;
        }
        //<summary>
        //更新一条记录
        //</summary>
        public void Update(Model.Manager manager)
        { 
        }
        //<summary>
        //删除一条记录
        //</summary>
        public void Delete(string managerid)
        { 
        }
        //<summary>
        //获得列表
        //<summary>
        public DataSet GetList(string manageid)
        {
            DataSet ds = new DataSet();
            ds = null;
            return ds;
        }
        ///<summary>
        ///得到一个对象实体
        ///</summary>
        public Model.Manager GetModel(string ManagerId)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("select ID, ManagerId, PassWord");
            strSql.Append(" from M_Manager");
            strSql.Append(" where ManagerId = @ManagerId");

            SqlParameter[] parameters = {
                 new SqlParameter ("@ManagerId", SqlDbType.VarChar, 20) };
            parameters[0].Value = http://www.mamicode.com/ManagerId;
            Model.Manager model = new Model.Manager();
            DataSet ds = DBUtility.DbHelperSQL.Query(strSql.ToString(), parameters);

            if (ds.Tables[0].Rows.Count > 0)
            {
                if (ds.Tables[0].Rows[0]["ID"].ToString() != "")
                {
                    model.ID = int.Parse(ds.Tables[0].Rows[0]["ID"].ToString());
                }
                model.ManagerId = ds.Tables[0].Rows[0]["ManagerId"].ToString();
                model.PassWord = ds.Tables[0].Rows[0]["PassWord"].ToString();
              
                return model;
            }
            else
            {
                return null;
            }
        }
    }
}

//OracleDAL.cs

using System.Data;

using System.Data.OracleClient;
using IDAL;
using DBUtility;
namespace OracleDAL
{
        //<summary>
        //数据访问类
        //</summary>
        public class Manager : IManager
        {
            public Manager()
            { 
            }
            //<summary>
            //添加一条记录
            //</summary>
            public int Add(Model.Manager model)
            {
                return 0;
            }
            //<summary>
            //更新一条记录
            //</summary>
            public void Update(Model.Manager model)
            { 
            }
            //<summary>
            //获得一个实体
            //</summary>
            public Model.Manager GetModel(string managerid)
            {
                return null;
            }
            //<summary>
            //删除一条记录
            //</summary>
            public void Delete(string managerid)
            {
            }
            //<summary>
            //获得列表
            //<summary>
            public DataSet GetList(string manageid)
            {
                DataSet ds = new DataSet();
                ds = null;
                return ds;
            }
        }
    }

注:在接口里定义的所有接口方法,在派生类里必须全部实现。

3. 实现抽象工厂模式
我们需要对代码进行进一步的重构和抽象,我们可以考虑用设计模式、条件外置以及反射来实现,具体方法如下:
(1)新建DALFactory类库项目,作为创建DAL对象的工厂,并新建DataAccess类放到这个抽象工厂里面去。并添加对IDAL项目的引用。
在DataAccess类中,我们创建对象通过配置文件和反射技术实现。通过配置文件的程序集名,决定加载具体的哪个DAL的程序集,动态组合类名来动态创建DAL对象,并返回IDAL接口对象,为了性能和使用方便,DataAccess类全部采用静态方法实现。
//DataAccess.cs
using IDAL;
using System.Reflection;
using System.Configuration;
namespace DALFactory
{
    //<summary>
    //在抽象工厂中创建DAL对象
    //</summary>
    public sealed class DataAccess
    {
        private static readonly string AssemblyPath = ConfigurationManager.AppSettings["DAL"];
        //<summary>
        //创建数据层接口
        //</summary>
        public static IDAL.IManager CreateManager()
        {
            string classNamespace = AssemblyPath + ".Manager";  //类名称
            object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);  // 反射
            return (Hui.IDAL.IManager)objType;  //类型转换
        }
}
(2)实现条件外置,即通过配置文件来实现对数据访问层的判断。我们可以把需要使用的DAL类型信息放在配置文件中,然后根据配置文件来选择创建具体的对象(DAL)。
在Web.config配置文件中增加当前数据访问层的信息:
 <appSettings>
    <add key="DAL" value="http://www.mamicode.com/SQLServerDAL"/>
  </appSettings>
此外,由于反射是一种非常耗费性能的操作。所以,我们可以通过缓存的方式来进行处理。DataAccess代码改为如下:
//DadaAccess.cs
       //使用缓存
        private static object CreateObject(string AssemblyPath, string classNamespace)
        {
            object objType = DataCache.GetCache(classNamespace);  //从缓存获取对象
            if (objType == null)  //缓存中没有
            {
                try
                {
                    //创建
                    objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
                    DataCache.SetCache(classNamespace, objType); // 写入缓存
                }
                catch
                { 
                }
            }
            return objType;
        }
        //<summary>
        //创建数据访问层
        //</summary>
        public static IDAL.IManager CreateManager()
        {
            string classNamespace = AssemblyPath + ".Manager";
            object objType = CreateObject(AssemblyPath, classNamespace);
            return (IDAL.IManager)objType;
        }
(3)为BLL项目添加对IDAL 和 DALFactory项目的引用。在BLL层中通过DALFactory 来创建DAL对象的接口调用,而不用关心具体该调用哪个DAL对象。BLL代码如下:
//BLLManager.cs
namespace BLL
{
    /// <summary>
    /// 业务逻辑类Manager
    /// </summary>
    public class Manager
    {
        //从工厂里面创建数据访问类
        IDAL.IManager dal = .DALFactory.DataAccess.CreateManager();
        public Manager()
        { 
        }
        ///<summary>
        ///查询一条数据
        ///</summary>
        public Model.Manager GetModel(string ManagerId)
        {
            return dal.GetModel(ManagerId);
        }
       //其他代码省略。。。。。。。。。。
    }
}

 
 

比较好的三层的理解(转载)---基于工厂模式