在开发一个项目的时候,有时候会碰到这样一个问题:就是项目开发到一半时,原先对数据库的访问走的是ADO.NET,中途项目经理突然要求改成使用EF实体模型去访问数据库......呃好吧!这样的话就需要去把原有的代码个修改,我们都知道在ADO.Net中,数据访问层DAL与业务逻辑层是耦合在一块的,当数据访问层的代码由原来的使用ADO.NET去访问数据库变为使用EF实体模型去访问数据库时,业务逻辑层BLL的代码也要去相应的改变(这是一件相当痛苦的事情)
1 //private UserEFDAL userefDal = new UserEFDAL();//当项目使用EF去访问数据库时创建一个实例 2 3 // private UserInfoDAL userDal = new UserInfoDAL();//当项目使用ADO去访问数据库时创建一个实例 4 //但是以上的方法当数据库访问的方法改变时,BLL层都要做出相应的改变并且不能保证改变后nwe出的实例名称相同 5 //那样就相当的悲剧了、、、、 6 public User Add(User userInfo) 7 { 8 return userDal.EFAdd(userInfo);//当通过两种方法new出来的实例名称不同时,悲催了。。。。 9 10 //return userefDal.ADOAdd(userInfo); 11 }
通过上面的简单的代码我们可以发现,当我们要切换数据库的访问方式时,需要不断的去改变new实例的名称,并且在EF中定义的添加的方法叫EFAdd,在ADO中定义的添加的方法叫ADOAdd,这样去修改代码的的工程非常的浩大(当你去改完时,估计你也被炒鱿鱼了),而我们又希望能够在当数据访问的方式不用的时候,BLL层的代码改变很少,或者不去改变BLL层的代码就能切换数据库访问的方式,我们希望在不同是数据访问方式不同时,内部的方法不变,我们规定在ADO或是EF中添加的方法为Add、修改的方法为Edit等。说到这,想必大家应该明白接下去要说的是什么了,没错,就是接口,在C#中什么是接口?所谓的接口其实就是一种规范,使得实现接口的类或结构在形式上保持一致,当一个类去继承该接口时,就必须实现该接口的所有成员,使用接口可以使程序更加清晰和条理化,这就是接口的好处。
所以,在上面的例子中,我们可以定义一个接口,让EFDAL和ADODAL去继承这个接口
//定义一个接口,当使用ADO.NET访问数据库或是时候EF实体模型访问时,都继承于这个接口 public interface IDALInterface { //这里还可以定义多个成员 User Add(User userInfo); } //EFDAL去继承IDALInterface这个接口 public class UserEFDAL : IDALInterface { DataModelContainer db = new DataModelContainer(); public User Add(User userInfo) { db.User.AddObject(userInfo); db.SaveChanges(); return userInfo; } } public class UserInfoDAL : IDALInterface//ADO.NET访问数据库时继承IDALInterface接口 { /// <summary> /// 实现IDALInterface接口 /// </summary> /// <param name="userInfo"></param> /// <returns></returns> public User Add(User userInfo) { //这里执行Add操作并返回插入的实体 return userInfo; } }
//BLL层代码 IDALInterface userDal = new UserEFDAL(); //在这里因为EF的DAL与ADo的DAL都继承自IDALInterface //当访问数据库的方式改变后,只要改变相应的数据库访问实例。这样就减少的代码的改动量 public User Add(User userInfo) { return userDal.Add(userInfo); //return userefDal.Add(userInfo); }
通过上面的例子,我们可以看到,只要在BLL层改变new不同的的实例,而不需要去改变太多的BLL的代码,就可以在不同的数据访问的方式切换,当然还是需要在BLL层修改代码。我们还是需要去一个个的找 IDALInterface userDal = new UserEFDAL();,然后去修改,有没有一种方法可以做到不去修改BLL层的代码而就能改变不同的数据库访问方式,答案当然是有的。我们可以创建一个工厂,通过反射的方法去创建一个实例
/// <summary> /// 创建一个简单的工厂来获取相应的程序集, /// </summary> /// <returns></returns> public static IDALInterface GetDALStyle() { string assemblyName = ConfigurationManager.AppSettings["assemblyName"];//通过配置文件来配置数据库的访问的方式 string typeName = ConfigurationManager.AppSettings["typeName"]; //通过反射创建一个实例 return Assembly.Load(assemblyName).CreateInstance(typeName) as IDALInterface; }
而相应的BLL的代码就改成
IDALInterface userDal = DALSimpleFactory.GetDALStyle();//通过工厂去创建一个实例 public User Add(User userInfo) { return userDal.Add(userInfo); //return userefDal.Add(userInfo); }
至此,我们就只需在配置文件中去修改相应的配置,就可以在不修改过多的代码下完成不同数据库访问方式的切换,大大减少的项目的开发的周期,通过工厂来得的实例,可以大大的减少BLL层与DAL层之间的耦合,也就是所谓的解耦。