您的位置:首页 > 运维架构

.Net PetShop3.0的数据访问技术及其改进

2005-09-14 10:41 549 查看
.Net PetShop3.0的数据访问技术及其改进
WWW.ISEAST.COM

使用ASP.NET开发网站,比起以前的ASP来,在界面设计和事件处理上有了很大改进。另外引入了(code behind)简化了页面文件中的代码,使我们能摆脱以前ASP页面中界面与VB Script交织的困惑。再通过把公用代码封装在用户控件(UserControl),在需要引用页面代码中加入Register 来引用控件即可,这有些像Java的Tag技术。

但是如果要实现企业应用,只应用界面的改进技术是远远不够的,更重要的是要实现数据库访问和传递方面的改进。为了示范Ado.Net的数据库编程模式,并且在性能上的不输于Java的J2EE,迅速提供了.Net版本的PetShop。虽然关于这两种技术实现PetShop的优劣争论不断,在这里试图分析PetShop数据访问技术的优点和不足,并提出改进的方法。

首先从http://www.gotdotnet.com/team/compare/下载最新的PetShop 3.0并安装后,其系统结构目录如下:



其目录按逻辑很清晰的分为业务逻辑层(BLL),数据访问层(DAL),实体层(MODEL),为了能同时访问Oracle和SqlServer,通过DALFactory根据配置文件来创建不同数据库的DAL对象来实现,而执行数据库Sql操作都放在一个Helper类中,如访问Oracle的用的就是OraHelper,它封装了所有对数据库的底层操作。下面是示例代码段:

public static int ExecuteNonQuery(OracleConnection conn, CommandType cmdType, string cmdText, params OracleParameter[] cmdParms)

{

OracleCommand cmd = new OracleCommand();

PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);

int val = cmd.ExecuteNonQuery();

cmd.Parameters.Clear();

return val;

}

我们看到了PetShop的数据访问方式,把所有数据读取,修改,新增的操作都用执行SQL语句来实现,并直接返回一个DataReader,接着DataReader是这样被填充到一个对象数组中:

public IList GetItemsByProduct(string productId)

{

// Declare array to return

IList itemsByProduct = new ArrayList();

// Create a database parameter

OracleParameter parm = new OracleParameter(PARM_PRODUCT_ID,OracleType.Char, 10);

//Set the parameter value

parm.Value = productId;

//Execute the query

using (OracleDataReader rdr = OraHelper.ExecuteReader(OraHelper.CONN_STRING_NON_DTC, CommandType.Text, SQL_SELECT_ITEMS_BY_PRODUCT, parm)) {

// Scroll through the results

while (rdr.Read()){

ItemInfo item = new ItemInfo(rdr.GetString(0).Trim(), rdr.GetString(1), rdr.GetDecimal(2), rdr.GetString(3), null);

//Add each item to the arraylist

itemsByProduct.Add(item);

}

}

return itemsByProduct;

}

这个方法通过OraHelper查询到数据,然后用ItemInfo item = new ItemInfo(rdr.GetString(0).Trim(), rdr.GetString(1), rdr.GetDecimal(2), rdr.GetString(3), null);填充完数据的具体对象,就此.Net PetShop完成了数据的O/R映射,并返回了填充完对象的ArrayList。

从以上.Net PetShop的数据访问实现方式来看有以下特点:

实现了多种数据库访问,并隔离了数据访问的具体实现方式

数据访问层和业务逻辑层的严格区分

用DataReader填充具体对象,而不是传递DataSet,节省了服务器资源;

但是这种方式也有它的不足之处:

在代码中出现大量的新增,删除和更新Sql语句,没有用一个类来实现这些通用的操作;

有大量参数赋值语句,可读性差,不利于代码的后期的维护;

从DataReader填充到对象属性需要重复写代码;

针对这些问题,通过应用Attribute和类反射机制,新增,删除和更新功能不需要再写Sql语句,参数赋值也不需要逐一写赋值过程,大大提高了编写数据访问代码的效率。

下面详细介绍其实现方式:

首先我们定义了以下Attribute,其主要代码如下:

public class DataDynamic : Attribute

{

public DataDynamic(string fieldName,bool isKey)

{

_fieldName = fieldName;

_isKey = isKey;

}

/// <summary>

/// The name of the field in the database

/// </summary>



}

private string _fieldName = "";

private bool _isKey = false;

private string _oldValue = "null";

}

在这个自定义属性中,描述了在数据库中的字段信息:fieldName(字段名),isKey(是否主键),oldValue(修改前的值);

然后在定义实体对象时需要定义其属性如下:

public class NewsObject

{

private string id = "NewId";

private string subject = "";

/// <summary>

/// The Id in the database

/// </summary>

[DataDynamic("id",true)]

public string Id

{

get

{

return id;

}

set

{

id = value;

}

}

/// <summary>

/// The name in the database

/// </summary>

[DataDynamic("subject",false)]

public string Subject

{

get

{

return subject;

}

set

{

subject = value;

}

}

}

在这里定义id为表主键,在BaseDataProvider数据访问组件中就是依靠这些信息自动产生更新和删除的Sql语句,而不再需要为每个对象个别定义Sql语句。访问该数据对象的代码变为:

BaseDataProvider dataProvider = new BaseDataProvider(null," NewsObject");

在BaseDataProvider中会获取数据并自动填充到NewsObject中,而删除一个对象则变为dataProvider.Delete(i),调用这个方法将自动删除相应的NewsObject,并产生删除数据库相应记录的Sql语句:delete NewsObject where id = 3。如果对某个NewsObject的信息做了修改,也只需调用dataProvider.Update(),就会产生相应的update语句,把数据自动更新到数据库。

可见,通过这样的改进,能减少重复代码的编写,提高系统实现效率。但是也要付出一定的性能代价,因为运用类反射会消耗一定的系统资源。究竟孰优孰劣,还是个人权衡吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: