科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件ASP.NET:自定义实体类简介(4)

ASP.NET:自定义实体类简介(4)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

自定义实体使您获得了面向对象的编程的丰富功能,并帮助您构建了可靠、可维护的 N 层体系结构的框架。

作者:microsoft 来源:Karl Seguin  2007年9月2日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

等一下!您并没有解决任何问题!

细心的读者可能注意到我前面提到 DataSet 的问题之一是它们并非强类型,这导致效率降低并增加了出现运行时错误的可能性。它们还需要开发人员深入了解基础数据结构。看一看上文的代码,您可能会注意到这些问题依然存在。但请注意,我们已经将这些问题封装到一个非常孤立的代码区域内;这表示您的类实体的使用者(Web 界面、Web 服务使用者、Windows 表单)仍然完全没有意识到这些问题。相反,使用 DataSet 可以将这些问题分散到整个代码中。

改进

上文的代码对显示映射的基本概念很有用,但可以在两个关键的方面进行改进。首先,我们需要提取并将代码填充到其自己的函数中,因为代码有可能会被重新使用:

'Visual Basic .NET

Public Function PopulateUser(ByVal dr As IDataRecord) As User

Dim user As New User

user.UserId = Convert.ToInt32(dr("UserId"))

'检查 NULL 的示例

If Not dr("UserName") Is DBNull.Value Then

user.UserName = Convert.ToString(dr("UserName"))

End If

user.Password = Convert.ToString(dr("Password"))

Return user

End Function

//C#

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;

}

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

最后,以上代码说明了封装的强大功能。处理 DataSet 中的 NULL 并非最简单的事,因为每次提取值时都需要检查它是否为 NULL。使用上述填充方法,我们在一个地方就轻松地解决了此问题,使我们的客户无需处理它。

映射到何处?



关于此类数据访问和映射函数的归属问题存在一些争论,即究竟是作为独立类的一部分,还是作为适当自定义实体的一部分。将所有用户相关的任务(获取数据、更新和映射)都作为 User 自定义实体的一部分当然很不错。这在数据库架构与自定义实体很相似时会很有用(比如在本例中)。随着系统复杂性的增加,这两个世界的差异开始显现出来,将数据层和业务层明确分离对简化维护有很大的帮助(我喜欢将其称为数据访问层)。将访问和映射代码放在其自己的层 (DAL) 上有一个副作用,即它为确保数据层与业务层的明确分离提供了一个严格的原则:

“永远不要从 System.Data 返回类或从 DAL 返回子命名空间”

自定义集合

到目前为止,我们只了解了如何处理单个实体,但您经常需要处理多个对象。一个简单的解决方案是将多个值存储在一个一般的集合(例如 Arraylist)中。这并非最理想的解决方案,因为它又产生了与 DataSet 有关的一些问题,即:

• 它们不是强类型,并且

• 无法添加自定义行为。

最能满足我们需求的解决方案是创建我们自己的自定义集合。幸亏 Microsoft .NET Framework 提供了一个专门为了此目的而继承的类:CollectionBase。CollectionBase 的工作原理是,将所有类型的对象都存储在专有 Arraylist 中,但是通过只接受特定类型(例如 User 对象)的方法来提供对这些专有集合的访问。也就是说,将弱类型代码封装在强类型的 API 中。

虽然自定义集合可能看起来有很多代码,但大多数都可以由代码生成功能或通过剪切和粘贴方便地完成,并且通常只需要一次搜索和替换即可。让我们看一看构成 User 类的自定义集合的不同部分:

'Visual Basic .NET

Public Class UserCollection

Inherits CollectionBase

Default Public Property Item(ByVal index As Integer) As User

Get

Return CType(List(index), User)

End Get

Set

List(index) = value

End Set

End Property

Public Function Add(ByVal value As User) As Integer

Return (List.Add(value))

End Function

Public Function IndexOf(ByVal value As User) As Integer

Return (List.IndexOf(value))

End Function

Public Sub Insert(ByVal index As Integer, ByVal value As User)

List.Insert(index, value)

End Sub

Public Sub Remove(ByVal value As User)

List.Remove(value)

End Sub

Public Function Contains(ByVal value As User) As Boolean

Return (List.Contains(value))

End Function

End Class

//C#

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));

}

}

通过实现 CollectionBase 可以完成更多任务,但上面的代码代表了自定义集合所需的核心功能。观察一下 Add 函数,可以看出我们只是简单地将对 List.Add(它是一个 Arraylist)的调用封装到仅允许 User 对象的函数中。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章