吾创Web

吾创网

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

看一下SQLServerDAL,前面有高人说了,那个SQLHelper类似于daab for .net,因此在这里我就不多话了,对daab for .net的讨论可以参看msdn的相关文章
来看Account.cs,里面有一个GetAddress方法,用来通过用户名获得用户资料。在这里面主要是分两步,第一步是获得参数并给其赋值,第二步是使用SqlDataReader来从数据库取值。
public AddressInfo GetAddress(string userId) {
AddressInfo address= null;
//获得参数列表

SqlParameter[] addressParms = GetAddressParameters();
//给参数赋值
addressParms[0].Value = userId;
//使用SqlDataReader来从数据库取值
using (SqlDataReader rdr = SQLHelper.ExecuteReader(SQLHelper.CONN_STRING_NON_DTC, CommandType.Text, SQL_SELECT_ADDRESS, addressParms)) {
if (rdr.Read()) {
address = new AddressInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2), rdr.GetString(3), rdr.GetString(4), rdr.GetString(5), rdr.GetString(6), rdr.GetString(7), rdr.GetString(8));
}
}

return address;
}


参数的获得比较复杂,先来看SqlDataReader的使用吧
using (SqlDataReader rdr = SQLHelper.ExecuteReader(SQLHelper.CONN_STRING_NON_DTC, CommandType.Text, SQL_SELECT_ADDRESS, addressParms)) {
if (rdr.Read()) {
address = new AddressInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2), rdr.GetString(3), rdr.GetString(4), rdr.GetString(5), rdr.GetString(6), rdr.GetString(7), rdr.GetString(8));
}
}

很简单的应用,SQLHelper.ExecuteReader的确是起到了和daab for .net差不多的作用。因为是获得个人资料,所以这里只有一条记录,就算是要处理需要分页的大数据量时,它也是这样用SqlDataReader返回所有的记录,但是之后就会把这些记录全部保存在Cache中,这样以后就不用查询数据库了。
GetAddressParameters方法用来获得此次操作需要的参数,它也是使用了SQLHelper的相关方法来完成的。
private static SqlParameter[] GetAddressParameters() {
//如果以前有保存参数,那就取出来

SqlParameter[] parms = SQLHelper.GetCachedParameters(SQL_SELECT_ADDRESS);

if (parms == null) {
parms = new SqlParameter[] {
new SqlParameter(PARM_USER_ID, SqlDbType.VarChar, 80)};
//创建新的参数数组,然后“缓存”起来
SQLHelper.CacheParameters(SQL_SELECT_ADDRESS, parms);
}

return parms;
}
我们可以接着看SQLHelper中的细节部分

//parmCache的定义
private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

//“缓存”参数
public static void CacheParameters(string cacheKey, params SqlParameter[] cmdParms) {
parmCache[cacheKey] = cmdParms;
}

/// <summary>
/// Retrieve cached parameters
/// </summary>
/// <param name="cacheKey">key used to lookup parameters</param>
/// <returns>Cached SqlParamters array</returns>

public static SqlParameter[] GetCachedParameters(string cacheKey) {
//从缓存中取出值
SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];
if (cachedParms == null)
return null;
SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];
//使用clone通过遍历得到一个新的参数数组
for (int i = 0, j = cachedParms.Length; i < j; i++)
clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();
return clonedParms;
}

用来缓存参数的parmCache实际上一个private static Hashtable,因为是static,所以自然是独一无二的了,创建一次就可以永远使用,起到和缓存差不多的效果。
在返回参数时要用clone来创建一个新的参数数组返回,是因为parmCache只有一个,而返回的参数数组则至少一个人用一个。更为重要的是,现在保存在parmCache的参数列表都是没有具体值的参数,而返回后则根据每个用户的不同情况而被赋于不同的值。

从这里子可以看出,有一个自己的daab是多么的重要。先前在论坛看到过有人喜欢用拖的方式来进行数据库的连接,那种做法我觉得不是很好,手写代码很重要的,写一个自己顺手的daab更是重要。


红色——文档重点;蓝色——自己的理解;绿色——不明白的地方

数据库可移植性

这一版本 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 的反射命名空间,可以加载某个特定(适当的)程序集SQLServerDALOracleDAL),使用该程序集创建某个对象(如Account类的对象)的实例

为了使应用程序更安全,为版本控制提供更好的支持,我们可以在应用程序配置文件(也就是这里的 web.configruntime))中添加要加载的程序集文件的证据,这意味着 .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层有针对性地进行编程——而这正是使用多层模式想要避免的!!!



posted on 2007-09-17 11:51  阿福哥  阅读(295)  评论(0编辑  收藏  举报