分享
 
 
 

笔记:使用自定义实体类和集合代替DataSet

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

《掌握 ASP.NET 之路:自定义实体类简介》(中文)原文见:

http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx

【另】:更多参考资料和链接也见原文,强烈推荐

DataSet的问题:

1、缺少抽象,开发人员必须了解其基础架构;

2、弱类型,返回的是System.Object,必须进行类型转换Convert.ToInt32等之后才能使用,降低了效率,增加了出错的可能性;

3、不是面向对象的,无法充分利用OO的技术。

使用DataSet,它的缺点将在复杂系统中成倍的扩大。

自定义实体类的挑战:

要求更多的代码。我们不是简单地获取数据并自动填充 DataSet,而是获取数据并手动将数据映射到自定义实体(必须先创建好)。由于这个工作是重复的,我们可以使用代码生成工具或者ORM映射。

自定义实体类的代码示例:

public class User {

#region "Fields and Properties"

private int userId;

private string userName;

private string password;

public int UserId {

get { return userId; }

set { userId = value; }

}

public string UserName {

get { return userName; }

set { userName = value; }

}

public string Password {

get { return password; }

set { password = value; }

}

#endregion

#region "Constructors"

public User() {}

public User(int id, string name, string password) {

this.UserId = id;

this.UserName = name;

this.Password = password;

}

#endregion

}

自定义实体类的优点:

1、可以让我们利用继承和封装等OO技术;

2、可以添加自定义行为;

3、属于强类型,可以获得代码自动完成功能(IntelliSense);

4、属于强类型,不太需要容易出错的强制类型转换。

对象和关系的映射:

public User GetUser(int userId) {

SqlConnection connection = new SqlConnection(CONNECTION_STRING);

SqlCommand command = new SqlCommand("GetUserById", connection);

command.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;

SqlDataReader dr = null;

try{

connection.Open();

dr = command.ExecuteReader(CommandBehavior.SingleRow);

if (dr.Read()){

User user = new User();

user.UserId = Convert.ToInt32(dr["UserId"]);

user.UserName = Convert.ToString(dr["UserName"]);

user.Password = Convert.ToString(dr["Password"]);

return user;

}

return null;

}finally{

if (dr != null && !dr.IsClosed){

dr.Close();

}

connection.Dispose();

command.Dispose();

}

}

以上代码还保留着DataSet弱类型需要转换这样的缺点,所以应该进一步改进,即将映射的转换过程提取到一个函数中,使这段代码能够重复使用——

public User PopulateUser(IDataRecord dr) {

User user = new User();

user.UserId = Convert.ToInt32(dr["UserId"]);

//检查 NULL 的示例

if (dr["UserName"] != DBNull.Value){

user.UserName = Convert.ToString(dr["UserName"]);

}

user.Password = Convert.ToString(dr["Password"]);

return user;

}

需要说明1:我们不对映射函数使用 SqlDataReader,而是使用 IDataRecord。这是所有 DataReader 实现的接口。使用 IDataRecord 使我们的映射过程独立于供应商。也就是说,我们可以使用上一个函数从 Access 数据库中映射 User,即使它使用 OleDbDataReader 也可以。如果您将这个特定的方法与 Provider Model Design Pattern(链接 1链接 2)结合使用,您的代码就可以轻松地用于不同的数据库提供程序。

需要说明2:数据访问是否该和自定义实体类放在一起?为了扩展和维护的方便,通常应该将数据访问层和业务层明确分离。

自定义集合:

简单的解决方案是使用Arraylist,但它的问题和DataSet相关,即也是弱类型,无法添加自定义行为。幸亏 Microsoft .NET Framework 提供了一个专门为了此目的而继承的类:CollectionBase。CollectionBase 的工作原理是,将所有类型的对象都存储在专有 Arraylist 中,但是通过只接受特定类型(例如 User 对象)的方法来提供对这些专有集合的访问。代码示例——

public class UserCollection :CollectionBase {

public User this[int index] {

get {return (User)List[index];}

set {List[index] = value;}

}

public int Add(User value) {

return (List.Add(value));

}

public int IndexOf(User value) {

return (List.IndexOf(value));

}

public void Insert(int index, User value) {

List.Insert(index, value);

}

public void Remove(User value) {

List.Remove(value);

}

public bool Contains(User value) {

return (List.Contains(value));

}

}

映射到自定义集合:

将我们的关系数据映射到自定义集合的过程与我们对自定义实体执行的过程非常相似。我们不再创建一个实体并将其返回,而是将该实体添加到集合中并循环到下一个:

public UserCollection GetAllUsers() {

SqlConnection connection = new SqlConnection(CONNECTION_STRING);

SqlCommand command =new SqlCommand("GetAllUsers", connection);

SqlDataReader dr = null;

try{

connection.Open();

dr = command.ExecuteReader(CommandBehavior.SingleResult);

UserCollection users = new UserCollection();

while (dr.Read()){

users.Add(PopulateUser(dr));

}

return users;

}finally{

if (dr != null && !dr.IsClosed){

dr.Close();

}

connection.Dispose();

command.Dispose();

}

}

添加自定义行为:

示例一

public User FindUserById(int userId) {

foreach (User user in List) {

if (user.UserId == userId){

return user;

}

}

return null;

}

示例二

public UserCollection FindMatchingUsers(string search) {

if (search == null){

throw new ArgumentNullException("search cannot be null");

}

UserCollection matchingUsers = new UserCollection();

foreach (User user in List) {

string userName = user.UserName;

if (userName != null && userName.StartsWith(search)){

matchingUsers.Add(user);

}

}

return matchingUsers;

}

绑定自定义集合:

自定义集合绑定到web控件和DataSet一样很简单(这是因为 CollectionBase 实现了用于绑定的 Ilist)。自定义集合可以作为任何控件的 DataSource,而 DataBinder.Eval 只能像您使用 DataSet 那样使用——

UserCollection users = DAL.GetAllUsers();

repeater.DataSource = users;

repeater.DataBind();

<!-- HTML -->

<asp:Repeater onItemDataBound="r_IDB" ID="repeater" Runat="server">

<ItemTemplate>

<asp:Label ID="userName" Runat="server">

<%# DataBinder.Eval(Container.DataItem, "UserName") %><br />

</asp:Label>

</ItemTemplate>

</asp:Repeater>

高级内容:

1、并发

2、性能

3、排序与筛选

4、代码生成

5、ORM映射

6、泛型

7、可以为空的类型

8、迭代程序

【强烈推荐参考:《DataSet与自定义实体类以及集合的比较》】

DataSets vs. Collections by Dino Esposito对比分析了DataSet, Typed DataSet和Custom Entities and Collections(定制业务实体和集合)作为multi-tier之间的数据传递,并阐述各自的适用情况(When to Use Which)。

文章建议:在小型项目中,考虑到预算、截至时间等因素,可以使用DataSet快速开发。如果项目时间长、投入多,业务逻辑复杂,则使用自定义实体类以及集合,对于维护、扩展、灵活、代码的优雅、单元测试等,都能带来益处。前期的投入是值得的。

文章建议阅读:For more information on these topics, take a look at the following blogs: Scott Hanselmans at Returning DataSets from WebServices is the Spawn of Satan and Represents All That Is Truly Evil in the World, Jelle Druyts at DataSets Are Not Evil, Andrew Conrads at Nix the DataSet??????, and ObjectSharp at DataSet FAQ.

各项比较:

DataSetTyped DataSetCustom EntitiesBuilt-in support for concurrency

Yes

Yes

To be added

Data Relationship

Yes

Yes

No

Serialization

Inefficient in .NET Framework 1.x

Same as DataSet, but can be improved

To be added

NULL values

No

Yes

To be added

Schema abstraction

Yes

Yes

Yes

Strong typing

No

Yes

Yes

Support for hierarchical data

Yes, but through a relational API

Yes, but through a relational API

Yes

Free-form data

No

No

Yes

Custom behavior

No

To be added

Yes

Ease of development

Yes

Yes

No, but can be improved through custom wizards and code generation

.NET data binding

Yes

Yes

To be added; requires the implementation of several additional interfaces

Interfacing with Web services

Costly, unless knowledge of the object is assumed on the client

Schema information is more precise and can be handled by the client

Yes

XML integration

Yes

Yes

To be added

Expression language

Yes

Yes

To be added

Data aggregation

Yes

Yes

To be added

如果采用Custom Entities,建议了解如下常用的Enterprise Design Patterns:

Design Patterns for Building a DAL

Pattern

Description

Active Record

The entity object stores its own data as well as any available methods. Clients get an instance of the object and work with it as needed.

Data Mapper

The entity object contains only its own data. A neat separation exists between data and behavior. Behavior is delegated to an array of separate classes specific to the object.

Table Data Gateway

Variation of Data Mapper that delegates the implementation of required behaviors to external, gateway classes not specific to the object. The gateway can take scalar and instance data and serve multiple business objects.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有