|
?
CSLA.NET''''s concurrency techniques
?
Unit of Work design pattern
?
Optimistic offline lock design pattern
?
Pessimistic offline lock design pattern
性能
与合理的灵活性和功能问题相对的是,我们经常担心细小的性能差异。尽管性能的确很重要,但提供适用于一切情况而不是最简单情况的通用原则通常很难。例如,将自定义集合与
DataSet 相比,哪个更快?使用自定义集合,您可以大量使用
DataReader,这是从数据库中提取数据的较快方式。但答案实际上取决于您使用它们的方式以及处理的数据类型,所以一般性的说明没有任何用。更重要的一点是要认识到,不管您能节省多少处理时间,与维护性方面的差异相比都可能微不足道。
当然,并不是说您不可能找到一个既具有高性能又可维护的解决方案。虽然我强调说答案实际上取决于您的使用方式,但的确有一些模式可以帮助您最大程度地提高性能。但是,首先要知道的是自定义实体与集合缓存以及
DataSet,并且能够利用相同的机制(类似于
HttpCache)。DataSet 的优势之一是它能够编写
Select 语句,以便只获取所需的信息。使用自定义实体时,您常常感到不得不填充整个实体以及子实体。例如,如果要通过
DataSet 显示一个 Organization 列表,您可以只提取
OganizationId、Name 和 Address
并将其绑定到重复器。使用自定义实体时,我总觉得还需要获取所有其他的 Organization 信息,如果该组织通过了 ISO
认证,则可能是一个位标记,即所有员工、其他联系信息等的集合。可能其他人没有碰到这个大难题,但幸运的是,如果我们愿意,我们可以对自定义实体进行很好的控制。最常用的方法是使用一种延迟加载模式,它只在首次需要时获取信息(可以很好地封装在属性中)。这种对各个属性的控制提供了通过其他方式无法轻易获得的巨大灵活性(请想象一下在
DataColumn 级别执行类似操作的情况)。
参考资料:
?
Lazy Load 设计模式
?
CSLA.NET lazy
load
排序与筛选
虽然 DataView 对排序和筛选的内置支持需要您了解有关 SQL
和基础数据结构的知识,但它提供的方便确实是自定义集合所不具备的。我们仍然可以排序和筛选,但首先需要编写功能。因为技术不一定是最先进的,所以代码的完整描述不属于本节要讨论的范围。大多数技术都很相似,例如使用筛选器类筛选集合以及使用比较器类进行排序,我认为不存在固定的模式。但是,的确存在一些参考资料:
?
Generic sort function
?
Sorting & Filtering Custom
Collections 教程
代码生成
解决概念上的障碍后,自定义实体与集合的主要缺点就是灵活性、抽象和维护性差所导致的代码数量的增加。实际上,您可能会认为我所说的维护成本和错误的降低这一切都抵不上代码的增加。虽然这一观点是成立的(同样,因为任何解决方案都不是完美无缺的),但可以通过设计模式和框架(例如
CSLA.NET)大大缓解此问题。代码生成工具与模式和框架完全不同,这些工具可以大大降低您实际需要编写的代码数量。本指南最初打算专门辟出一节详细介绍代码生成工具,特别是流行的免费
CodeSmith;但现有的许多参考资料都可能超出了我自己对该产品的认识。
在继续之前,我认识到代码生成听起来像天方夜谭一样。但经过正确的使用和理解后,它的确是您工具包中不可缺少的一个强大的武器,即使您没有处理自定义实体也是如此。虽然代码生成的确不仅仅适用于自定义实体,但很多都是专为自定义实体而设计的。原因很简单:自定义实体需要大量重复代码。
简言之,代码生成是如何工作的?构想听起来好像遥不可及甚至反而会降低效率,但您基本上通过编写代码(模板)来生成代码。例如,CodeSmith
附带了许多强大的类,使您可以连接到数据库并获取所有属性:表、列(类型、大小等)和关系。获得这些信息后,我们前面讨论的大部分工作都可以自动完成。例如,开发人员可以选择一个表,然后使用正确的模板自动创建自定义实体(带有正确的字段、属性和构造函数),并获得映射函数、自定义集合以及基本的选择、插入、更新和删除功能。甚至还可以更进一步,实现排序、筛选以及我们提到的其他高级功能。
CodeSmith 还附带了许多现成的模板,可以作为很好的学习资料。最后,CodeSmith 还为实现 CSLA.NET
框架提供了许多模板。我最初只花了几个小时来学习基本概念、熟悉 CodeSmith
的功能,但它为我节省的时间已经多得无法计算了。另外,如果所有的开发人员都使用相同的模板,代码的高度一致性将使您能够轻松地继续其他人的工作。
参考资料:
?
Code Generation with CodeSmith
?
CodeSmith 主页
O/R 映射器
即使因为对 O/R
映射器知之甚少使我不敢随便对它们发表议论,但它们自身的潜在价值使其不容忽视。代码生成器生成基于模板的代码,供您复制并粘贴到您自己的源代码中,而 O/R
映射器则在运行时通过某种配置机制动态生成代码。例如,在 XML 文件中,您可以指定某个表的列 X 映射到某个实体的属性
Y。您仍然需要创建自定义实体,但是集合、映射和其他数据访问函数(包括存储过程)都是动态创建的。从理论上讲,O/R
映射器几乎可以完全解决自定义实体存在的问题。随着关系世界和对象世界的差异越来越明显以及映射过程越来越复杂,O/R 映射器的价值就变得越发不可限量了。O/R
映射器的两个缺点据说就是不够安全和性能较差(至少在 .NET
环境中是这样)。根据我所阅读的资料,我确信它们并不是不够安全,虽然在有些情况下性能较差,但在另外一些情况下却表现突出。O/R
映射器并不适合所有情况,但如果您要处理复杂的系统,则应尝试一下它们的功能。
参考资料:
?
Mapper 设计模式
?
Data Mapper 设计模式
?
Wilson ORMapper
?
Frans Bouma 关于 O/R
映射的帖子
?
LLBGenPro
?
NHibernate
.NET Framework 2.0 的功能
即将面世的 .NET Framework 2.0
版将改变我们在本指南中讨论的一些实施细节。这些改变将减少支持自定义实体所需的代码数量,并有助于处理映射问题。
泛型
议论颇多的泛型之所以存在,主要原因之一就是为了向开发人员提供现成的强类型的集合。我们避开 Arraylist
等现有集合是因为它们属于弱类型。泛型提供了与当前集合同样的方便性,而且它们属于强类型。这是通过在声明时指定类型来实现的。例如,我们可以替换
UserCollection 而不需要增加代码,然后只需创建一个 List<T>
泛型的新实例并指定我们的 User 类即可: ''''Visual Basic .NET
Dim users as new IList(of User)
//C#
IList<User> users = new IList<user>();
声明后,我们的 user 集合就只能处理 User
类型的对象了,这为我们提供了编译时检查和优化的所有优点。
参考资料:
?
Introducing .NET Generics
?
An Introduction to C# Generics
可以为空的类型
可以为空的类型实际上就是由于其他原因而非上述原因而使用的泛型。处理数据库时面临的挑战之一就是正确一致地处理支持 NULL
的列。在处理字符串和其他类(称为引用类型)时,您只需为代码中的某个变量指定
nothing/null: ''''Visual Basic .NET
if dr("UserName") Is DBNull.Value Then
user.UserName = nothing
End If
//C#
if (dr["UserName"] == DBNull.Value){
user.UserName = null;
}
也可以什么都不做(默认情况下,引用类型为
nothing/null)。这对值类型(例如整数、布尔值、小数等)并不完全一样。您当然也可以为这些值指定
nothing/null,但这样将会指定一个默认值。如果您只声明整数,或者为其指定
nothing/null,变量的值实际上将为
0。这使其很难映射回数据库:值究竟为 0 还是
null?可以为空的类型允许值类型具有具体的值或者为空,从而解决了这个问题。例如,如果我们要在
userId 列中支持 null 值(并不是很符合实际情况),我们会首先将
userId 字段和对应的属性声明为可以为空的类型: ''''Visual Basic .NET
Private _userId As Nullable(Of Integer)
Public Property UserId() As Nullable(Of Integer)
Get
Return _userId
End Get
Set(ByVal value As Nullable(Of Integer))
_userId = value
End Set
End Property
//C#
private Nullable<int> userId;
public Nullable<int> UserId {
get { return userId; }
set { userId = value; }
}
然后利用 HasValue 属性判断是否指定了
nothing/null: ''''Visual Basic .NET
If UserId.HasValue Then
Return UserId.Value
Else
Return DBNull.Value
End If
//C#
if (UserId.HasValue) {
return UserId.Value;
} else {
return DBNull.Value;
}
参考资料:
?
Nullable types in C#
?
Nullable types in VB.NET
迭代程序
我们前面讨论的 UserCollection
示例只展示了自定义集合中可能需要的基本功能。有一个操作无法通过所提供的实现来完成,即通过一个 foreach
循环在集合中循环。要完成此操作,您的自定义集合必须具有实现 IEnumerable
接口的枚举数支持类。这是一个非常直观且重复性较强的过程,但却引入了更多的代码。C# 2.0 引入了新的 yield
关键字来为您处理此接口的实现细节。Visual Basic .NET 中当前没有与新的 yield 关键字等效的关键字。
参考资料:
?
What''''s new In C# 2.0 - Iterators
?
C# Iterators
返回页首
小结
请勿轻率地做出向自定义实体与集合转换的决定。这里有许多需要考虑的因素。例如,您对 OO
概念的熟悉程度、可用来熟悉新方法的时间以及您打算部署它的环境。虽然总体上它们有很大的优点,但并不一定适合您的特定情况。即使适合您的情况,它们的缺点也可能会打消您使用它们的念头。还要记住有许多可替代的解决方案。Jimmy
Nilsson 在他的 Choosing Data Containers for .NET 中概述了其中的某些替代方案,此专栏系列包括 5
部分(1、2、3、4、5)。
自定义实体使您获得了面向对象的编程的丰富功能,并帮助您构建了可靠、可维护的 N 层体系结构的框架。本指南的目的之一是让您从构成系统的业务实体,而不是一般的
DataSet 和 DataTable
的角度来考虑您的系统。我们还讨论了一些关键的问题,不管您选择的途径(即设计模式)、对象世界与关系世界的差异(了解详细信息)以及 N
层体系结构是什么,您都应注意这些问题。请记住,您之前花费的时间会在系统的整个生命周期内为您带来更多的回报。
相关书籍
?
Microsoft ASP.NET Coding Strategies with the
Microsoft ASP.NET Team
?
Expert C# Business Objects
?
Expert One-on-One Visual Basic .NET Business
Objects
1http://www.hanselman.com/blog/PermaLink.aspx?guid=d88f7539-10d8-4697-8c6e-1badb08bb3f5
? 2005 Microsoft Corporation
版权所有。保留所有权利。使用规定。
上一页 [1] [2] [3] [4] [C语言系列]NET 中C#的switch语句的语法 [网页制作]需要掌握的八个CSS网页布局技巧! [办公软件]掌握Excel十二条操作技巧,让工作更效益 [办公软件]喧宾不夺主—轻松掌握Word对象的叠放次序 [办公软件]掌握Word英文大小写转换,提高工作效益 [操作系统]全方位掌握系统自动更新的设置 [操作系统]掌握基本输入输出系统CMOS的使用及维护知识 [操作系统]轻松掌握10个Windows2003的配置技巧下篇 [操作系统]轻松掌握10个Windows2003的配置技巧上篇 [网络技术]让DHCP服务器不再是累赘就得掌握使用方法和技巧中…
|