红色——文档重点;蓝色——自己的理解;绿色——不明白的地方
数据库可移植性
这一版本 Microsoft .NET Pet Shop 的关键需求之一是提供支持 Oracle 和 SQL Server 数据库的应用程序实现。 在设计应用程序的数据库访问机制时,我们可以选择应该使用哪一个数据库提供程序;可以使用通用的OLE-DB 托管提供程序或者数据库特定的优化了性能的 .NET 托管提供程序,比如 .NET 框架1.1 中提供的 SQL Server 和 Oracle 托管提供程序。 应用程序的关键需求之一是创建一个高性能的解决方案,因此我们选择用数据库本身的 .NET 托管提供程序构建应用程序。 关于托管提供程序和通用 OLE-DB 提供程序之间的性能差异分析,读者可以参考 Using .NET Framework Data Provider for Oracle to Improve .NET Application Performance,该文档说明了厂商特定的提供程序能够比等价的 OLE-DB 提供程序性能好两到三倍。
在选择数据库特定的访问类时进行的考虑是,我们需要为每个即将支持的数据库平台遍写一个单独的数据访问层,因此应用程序将包含更多代码。 虽然两个数据访问层共享很多公共代码,但还是要明显地分别针对具体数据库。
为了简化数据库访问类的使用,我们选择 GoF概述的“工厂设计模式”,通过反射,动态地在运行时加载正确的数据访问对象。
工厂设计模式是这样实现的: 创建一个 C# 接口,其中对于数据库访问类必须公开(实现?)的每个方法都要声明一个方法(IDAL完成的工作)。 对于每一个要支持的数据库,都创建一个实现数据库特定代码的具体类,以执行接口(也称“协定”)中的每一项操作(DAL完成的工作)。
为了支持运行时确定加载哪一个具体类,需要创建第三个类,也就是工厂类。
注意:DALFactory的具体功能:
功能1:它从配置文件中读入一个值,以确定应该使用“反射”加载的是哪一个程序集
功能2:通过 .NET 的反射命名空间,(可以)加载某个特定(适当的)程序集(SQLServerDAL或OracleDAL),并使用该程序集创建某个对象(如Account类的对象)的实例。
为了使应用程序更安全,为版本控制提供更好的支持,我们可以在应用程序配置文件(也就是这里的 web.config(runtime))中添加要加载的程序集文件的“证据”,这意味着 .NET 框架将只加载我们在编译期间签过名而且有正确版本号的程序集。
图 10 说明了业务逻辑类、工厂类和数据库访问类是如何相互操作的。这一创建的解决方案最重要的优势是数据库访问类可以在业务逻辑类之后编译(???),只要数据访问类实现了IDAL 接口。 这意味着,如果要创建应用程序的 DB2 版本,我们不需要改动业务逻辑层(或者 UI 层)。
创建 DB2 兼容版本的步骤如下:
1.创建 DB2 的数据库访问类,它应该实现 IDAL 接口。
2.将 DB2 访问类编译成一个程序集。
3.测试和部署新的数据库程序集到一台运行中的服务器上。
4.更改配置文件,指向新的数据库访问类。(!!!直接在web.config文件中修改即可!!!)
无需更改或重新编译业务逻辑组件。
图 10. .NET Pet Shop 中 DAL 工厂类的实现
----------------------------------------------------------------------------------
根据上图总结出的访问流程:(修订了SQLServer学习笔记中的访问流程)
1、 通过PetShop.DALFactory.Product.Create()选择加载了一个正确的DAL组件(比如SQLServerDAL)
2、 创建了一个正确的DAL层组件的Product类的实例
3、 返回了一个该Product类在IDAL层的接口IProduct
存在的疑问:
1、 什么不直接返回已经选出来的,适当的DAL组件(如SQLServerDAL)的适当的对象(如Product),而返回了一个该对象在IDAL层的引用?
2、 IDAL层的引进究竟目的何在?是否单纯为了规范下层DAL组件所必须实现的数据访问方法?还是说只要使用工厂模式就必须定义接口,并且即使使用反射确定了应该正确加载的DAL组件的对象,也必须返回对象接口引用?
3、 自己的答案:如果不返回接口,那么上层BLL在得到返回的DAL组件对象之后,就有可能知道在下层究竟使用的是SQLServerDAL还是OracleDAL,这就有可能在BLL层有针对性地进行编程——而这正是使用多层模式想要避免的!!!