适用于
Microsoft® NET 应用程序
摘要学习向 Microsoft NET 应用程序公开数据的最佳方式以及如何实现一个有效的策略以便在分布式应用程序的层间传递数据(本文包含一些指向英文站点的链接)
目录
简介
将关系数据映射到业务实体
实现数据访问逻辑组件
实现业务实体
事务处理
验证
异常管理
授权与安全性
部署
附录
合作者
简介
在设计分布式应用程序时需要确定如何访问和表示与该应用程序相关联的业务数据本文提供一些指导原则以帮助您选择公开数据保持数据和在应用程序的层间传递数据的最佳方式
图 所示为分布式应用程序中的常见层本文区分业务数据与使用这些数据的业务过程并且仅在需要明确说明时讨论业务过程层同样本文仅在直接涉及数据表示方式(例如 Microsoft® ASPNET Web 页面公开业务数据的方式)时讨论表示层图 中使用了两个新术语数据访问逻辑组件和业务实体组件本文后面将解释这些术语
图 分布式应用程序中数据的访问与表示
多数应用程序将数据存储在关系数据库中除此之外还有其他数据存储方式但本文重点讨论 NET 应用程序与关系数据库交互的方式而并不专门讨论它如何与平面文件非关系数据库等其他数据存储中的数据进行交互
本文明确区分保持逻辑与数据本身将保持逻辑与数据区分开来的原因如下
独立的数据保持组件可以将应用程序与数据源名称连接信息字段名等数据库相关内容隔离开
现在的许多应用程序都采用 XML Web servicesMicrosoft 消息队列(亦称 MSMQ)等松散耦合的基于消息的技术这些应用程序通常通过传递业务文档而不是传递对象进行通信
为区分保持逻辑与数据本身本文提出了两种不同的组件类型
数据访问逻辑组件数据访问逻辑组件从数据库中检索数据并把实体数据保存回数据库中数据访问逻辑组件还包含实现数据相关操作所需的所有业务逻辑
业务实体组件数据用来表示产品订单等现实世界中的业务实体在应用程序中表示这种业务实体的方法非常多例如 XMLDataSet面向对象的自定义类等这取决于应用程序的物理和逻辑设计限制本文后面将详细讨论各种设计方案
数据访问逻辑组件
数据访问逻辑组件代表调用程序提供对数据库执行以下任务的方法
在数据库中创建记录
读取数据库中的记录并把业务实体数据返回给调用程序
使用调用程序提供的修改后的业务实体数据更新数据库中的记录
删除数据库中的记录
执行上述任务的方法通常称为CRUD方法这是由各项任务的首字母组成的一个缩写词
数据访问逻辑组件还提供对数据库实现业务逻辑的方法例如数据访问逻辑组件可能包含一个查找目录中本月销售额最高的产品的方法
通常数据访问逻辑组件访问一个单一数据库并封装了针对该数据库中一个表或一组相关表的数据相关操作例如可以定义一个数据访问逻辑组件来处理数据库中的 Customer 表和 Address 表同时定义另一个数据访问逻辑组件来处理 Orders 表和 OrderDetails 表本文后面将讨论将数据访问逻辑组件映射到数据库表的设计决策
表示业务实体
每个数据访问逻辑组件都处理一种特定类型的业务实体例如Customer 数据访问逻辑组件处理 Customer 业务实体表示业务实体的方式很多这取决于诸如以下因素
是否需要把业务实体数据与 Microsoft Windows® 窗体或 ASPNET 页面中的控件绑定在一起?
是否需要对业务实体数据执行排序或搜索操作?
应用程序是每次处理一个业务实体还是通常处理一组业务实体?
是本地部署还是远程部署应用程序?
XML Web services 是否使用该业务实体?
性能可缩放性可维护性编程方便性等非功能性要求的重要程度如何?
本文将概述以下实现选项的优缺点
XML使用 XML 字符串或 XML 文档对象模型 (DOM) 对象来表示业务实体数据XML 是一种开放而灵活的数据表示格式可用于集成各种类型的应用程序
DataSetDataSet 是缓存在内存中的表它是从关系数据库或 XML 文档中获得的数据访问逻辑组件可以使用 DataSet 来表示从数据库中检索到的业务实体数据您可以在应用程序中使用该 DataSet
有类型的 DataSet有类型的 DataSet 是从 ADONET DataSet 类继承而来的类它为访问表和 DataSet 中的列提供了具有严格类型的方法事件和属性
业务实体组件这是一种自定义类用于表示各种业务实体类型您可以定义保存业务实体数据的字段并定义将此数据向客户端应用程序公开的属性然后使用在该类中定义的字段来定义方法以封装简单的业务逻辑此选项并不通过 CRUD 方法实现与基础数据访问逻辑组件的数据传递而是通过客户端应用程序直接与数据访问逻辑组件进行通信以执行 CRUD 操作
带有 CRUD 行为的业务实体组件按上述方法定义一个自定义实体类并实现调用与此业务实体相关联的基础数据访问逻辑组件的 CRUD 方法
注意如果希望以一种更加面向对象的方式使用数据可以使用另一种替代方法即定义一个基于公共语言运行库的反射功能的对象保持层您可以创建一个使用反射功能来读取对象属性的架构并使用映射文件来描述对象与表之间的映射然而要有效地实现上述方法需要大量的基础结构代码投入对于 ISV 和解决方案提供商来说这种投入或许可以接受但对于大多数组织则不可行有关这方面的讨论超出了本文的范围这里不再论述
技术因素
图 所示为影响数据访问逻辑组件和业务实体实现策略的一些技术因素本文将分别讨论这些技术因素并提供相关建议
图 影响数据访问逻辑组件和业务实体设计的技术因素
将关系数据映射到业务实体
数据库通常包含许多表这些表之间的关系通过主键和外键来实现当定义业务实体以在 NET 应用程序中表示这些数据时必须确定如何把这些表映射到业务实体
请考虑图 所示的假想零售商数据库
图 假想的关系数据库中的表关系
下表总结了示例数据库中的关系类型
当定义业务实体以在数据库中建立信息模型时应考虑要如何在您的应用程序中使用这些信息应当标识封装您的应用程序的功能的核心业务实体而不是为每个表定义单独的业务实体
该假想零售商的应用程序中的典型操作如下
获取(或更新)客户的有关信息(包括地址)
获取客户的订单列表
获取特定订单的订购项目列表
创建新订单
获取(或更新)一个或一组产品的有关信息
为满足这些应用程序要求该应用程序要处理三个逻辑业务实体CustomerOrder 和 Product对于每个业务实体都将定义一个单独的数据访问逻辑组件如下所示
Customer 数据访问逻辑组件此类将为检索和修改 Customer 表和 Address 表中的数据提供服务
Order 数据访问逻辑组件此类将为检索和修改 Order 表和 OrderDetails 表中的数据提供服务
Product 数据访问逻辑组件此类将为检索和修改 Product 表中的数据提供服务
图 所示为这些数据访问逻辑组件与它们所表示的数据库中的表之间的关系
图 定义向 NET 应用程序公开关系数据的数据访问逻辑组件
有关如何实现数据访问逻辑组件的说明请参阅本文后面的实现数据访问逻辑组件
将关系数据映射到业务实体的建议
要将关系数据映射到业务实体请考虑以下建议
花些时间来分析您的应用程序的逻辑业务实体并为之建立模型不要为每个表定义一个单独的业务实体建立应用程序的工作方式模型的方法之一是使用统一建模语言 (UML)UML 是一种形式设计注释用于在面向对象的应用程序中建立对象模型并获取有关对象如何表示自动过程人机交互以及关联的信息
不要定义单独的业务实体来表示数据库中的多对多表可以通过在数据访问逻辑组件中实现的方法来公开这些关系例如前面示例中的 OrderDetails 表没有映射到单独的业务实体而是通过在 Order 数据访问逻辑组件中封装 OrderDetails 表来实现 Order 与 Product 表之间的多对多关系
如果具有返回特定业务实体类型的方法请把这些方法放在该类型对应的数据访问逻辑组件中例如当检索一个客户的全部订单时返回值为 Order 类型因此应在 Order 数据访问逻辑组件中实现该功能反之当检索订购某特定产品的全部客户时应在 Customer 数据访问逻辑组件中实现该功能
数据访问逻辑组件通常访问来自单一数据源的数据当需要聚合多个数据源的数据时建议分别为访问每个数据源定义一个数据访问逻辑组件这些组件可以由一个能够执行聚合任务的更高级业务过程组件来调用建议采用这种方法的原因有二
事务管理集中在业务过程组件中不需要由数据访问逻辑组件显式控制如果通过一个数据访问逻辑组件访问多个