蛙蛙请教:如何让DAL和BLL实现松散耦合(实现组件的热拔插)。
蛙蛙请教:如何让DAL和BLL实现松散耦合(实现组件的热拔插)。
我有个构想,就是让BLL和DAL层之间实现真正的松散耦合,基于托管组件的的系统,在BLL里调用DAL层方法的时候耦合性比较强,需要调用RunSqlserverSP()或者RunOracleSP()这样的方法,如果DAL层更换了数据库的话,BLL层有一批代码还得重写。有些人可能了解petshop那样的架构,定义一系列接口,分别写一个oracle和sqlserver的实现,然后运行的时候根据配置决定用哪个实现类,利用反射来加载DAL程序集再执行。
我想能不能用一个xml文件来映射DAL和BLL之间的关系,这样BLL就是就是纯粹的业务逻辑,而和DAL层没有什么关系了,而DAL层可以单独维护,进行独立的单元测试,DAL用sqlserver还是用oracle自己决定,最后返回DataSet让BLL层使用。BLL层使用类似下面的代码来和DAL层交互。
emp1.EmployeeID = 1; //这个是主键,按理说是自动生成的,不是指定的
emp1.BirthDate = DateTime.Parse("1983/05/03");
emp1.City = "石家庄";
emp1.Country ="中国";
emp1.FirstName ="蛙蛙";
emp1.LastName = "王子";
//创建一个DAL和BLL层的映射对象,构造函数的参数是DAL层的类型的
//字符串表示,这里就是DAL程序集的Employee类,实际运行的时候是
//根据元数据和反射来把这个类型缓存起来,然后再调用它上面的方法
BLLDALMappting bdm = new BLLDALMappting("DAL.Employee");
//执行映射对象上的Insert对象,添加一个新员工,原理就是根据元数据里
//Employee实体和DAL.Employee里某个方法及其参数的映射来执行的。实体的
//属性和DAL层的方法的参数相对应,这用元数据映射,然后给员工实体类的
//实例赋值会直接传递到DAL层具体方法的参数里,并执行。返回的值是影响
//数据库记录的条数
if(bdm.Insert(emp1)!=-1)
Console.WriteLine("蛙蛙王子添加成功");
//更新的时候必须要设置主键以及要更新的对象的值
//主键用来选定指定的实体,然后调用映射对象的update
//方法就可以完成持久化操作了,具体细节由DAL层完成。
EmployeeEntity emp2 = new EmployeeEntity();
emp2.EmployeeID = 1;
emp2.FirstName = "谁染";
emp2.LastName = "枫林醉";
if(bdm.Update(emp)!=-1)
Console.WriteLine("蛙蛙王子修改成谁染枫林醉了");
//执行选择操作的时候可以先指定主键EmployeeID,然后执行
//Select方法,这样就会emp3里的其它成员就会被自动填充了,
//然后你可以把这个实体可以直接绑定到界面控件上
EmployeeEntity emp3 = new EmployeeEntity();
emp3.EmployeeID = 1;
bdm.Select(emp3);
Console.WriteLine("谁染枫林醉所在的城市是"+emp3.City);
//如果返回的是个多条数据,可以通过访问实体的ResultData来获取
//数据集,这常用来查询的时候返回多个结果。
DataSet ds = emp3.ResultData;
//删除也很简单,指定主键,调用容器的Delete方法就会调用DAL层的
//方法把这个删除操作在数据库里执行
EmployeeEntity emp4 = new EmployeeEntity();
emp4.EmployeeID =1;
if(bdm.Delete(emp4)!=-1)
Console.WriteLine("谁染枫林醉被删除了");
总的来说,就是业务逻辑层呢,只执行实体的标准的CRUD操作,而这些CRUD操作实际实现是在DAL层做。他们之间的连系由XML文件来映射,XML文件为每个实体的CRUD操作映射一个DAL层命令(方法),每个命令包含这个方法的签名(参数的类型,方向,顺序),以便让BLL层通过反射来调用这些方法。
其实呢,实体的CRUD操作应该直接映射存储过程,但是有的数据库系统没有存储过程,也不能执行多条SQL语句,所以呢,我就想到了,单独用一个DAL层来执行一些代替存储过程的简单操作,这里不做复杂的逻辑,只是从数据库里选择数据并返回,或者修改数据库。这样的话,业务层的一条业务就有可能跨越好几个数据库,因为它不必关心DAL层是怎么实现的。
还有几个问题需要讨论:
1.事务处理:我想把数据库事务都放到DAL层里,让DAL层自己维护执行多条语句的事务,BLL层只要最后结果。如果需要分布式事务的话,也都在DAL层里协调。
2.并发处理:并发也集中在DAL层里处理,或者在存储过程里处理。
3.错误处理,因为DAL层是通过反射来调用执行的,所以DAL层里如何抛出详细的错误到BLL层呢,好像只能抛出一些反射的错误,是不是需要在DAL层单独运行一个错误处理层呀。
4.调试和测试:因为DAL层和BLL层松散耦合,单独调试DAL层好调试,但是BLL层就不好调试了,而且单元测试也不好做,所以,我想调试和进行单元测试的时候可以直接把DAL层引用到BLL层里,通过直接调用测试和调试,然后部署的时候再让他们分开,因为DAL层可能运行再A服务器,而BLL层运行在B服务器。
5.性能问题:这里面因为用了反射,势必影响性能,所以我的想法是,在应用程序启动的时候运行反射,把这个发现的类和方法保存到一个静态的HASHTABLE里面,然后调用DAL层方法的时候,从这个hashtable里直接执行方法,这样可能会提高一些性能。当然dal方法的参数等都要缓存起来,就像缓存sql语句以及SQL参数一样。
我感觉这样就可以实现组件的热拔插,在运行的时候,把DAL层里的某个方法替换掉,让它从访问SQLSERVER数据库转移到访问ORACLE数据库,减少停机的次数。而且DAL层的方法尽量是以静态方法发布,就像调用一些服务,而且最好一个是一个,不能重载。
不知道我这个想法有没有实际意义,因为现在COM+服务,WEB服务,remoting服务等也都能让层和层之间实现松散耦合,而我这个利用了反射和晚期绑定的方案有没有价值,欢迎板砖哦,这个系统我正在实现呢,先征求一下大家的意见。