分布式应用架构中的数据传输对象(DTO)
Written by: Rickie Lee
Dec. 1, 2004
在分布式架构中,相关层在物理部署上实现分离,通过网络或跨进程调用远程对象或服务。在这种分布式架构中,需要定义有效的数据传输对象(Data Transfer Object, DTO)来实现层与层之间的数据传输。
因为远程调用需要跨越网络或进程,因此会比较慢。通过使用DTO,在单一远程调用中传输更多的数据信息,减少远程调用的次数,提高分布式调用的性能。
下面分析一些比较常用的数据传输对象(DTO):
1.DataSet
DataSet是缓存在内存中的表,它是从关系数据库或 XML 文档中获得的。可以使用 DataSet来表示从数据库中检索到的业务实体数据,然后可以在层与层之间使用DataSet来传递数据。Microsoft提供的范例Duwamish 7.0中使用大量的DataSet来实现层与层之间的数据传递,如Presentation层与BusinessFacade层等等。
优点:(1)DataSet类由.Net Framework内置实现,不必编写和维护额外的类。(2)DataSet可以与Windows Form和Web Form的内置控件直接交互,如DataGrid等。(3)DataSet支持序列化XML,不仅包括内容序列化,还包括Schema。(4)非连接的数据模式。(5)DataSet 可以包含数据的集合,能够表示复杂的数据关系。
缺点:(1)互操作性问题,因为DataSet类是ADO.NET提供的,因此要求Client端在.Net Framework平台上运行。(2)陈旧的数据,因为DataSet包含的数据是Database的快照,如果Database的数据经常改变,则不推荐采用DataSet。(3)依赖Database schema,访问DataSet中数据时,要求显式指定字段类型和数据表之间的关系,如果Database schema发生变化,相应的code也要变化。要访问 DataSet 中的表,客户端代码必须使用整数索引生成器或字符串索引生成器来索引 DataTable 集合。要访问特定列,必须使用列编号或列名称索引 DataColumn 集合。(4)缺乏类型安全,当从DataSet中取值时,需要显式指定要转换的数据类型,这样容易产生错误。(5)性能问题。实例化和封送处理 DataSet 会增加运行时负担。
2.有类型的DataSet
有类型的DataSet是从 ADO.NET DataSet 类继承而来的类,包含具有严格类型的方法、属性和类型定义以公开 DataSet 中的数据和元数据的类。
优点:除了上述DataSet的部分优点外,有类型的 DataSet 还提供了数据验证支持(在编译时进行类型检查,无效的表名称和列名称将在编译时而不是在运行时检测),并且简化代码的编写,提高代码的可读性。
缺点:(1)具有DataSet的大部分缺点,除了提供类型安全。(2)另外,需要编写或维护用来描述typed interface的XML Schema,不过幸好VS.Net IDE提供工具支持。(3)部署问题。必须将包含有类型的 DataSet 类的程序集部署到使用业务实体的所有层。(4)可扩展性问题。如果修改了数据库架构,则可能需要重新生成有类型的 DataSet 类以支持新架构。重新生成过程将不会保留在有类型的 DataSet 类中实现的任何自定义代码。必须将包含有类型的 DataSet 类的程序集重新部署到所有客户端应用程序中。
有类型的方法和属性的提供使得使用有类型的 DataSet 比使用通用 DataSet 更方便。使用有类型的 DataSet 时,IntelliSense 将可用。有类型的 DataSet 的实例化和封送处理性能与通用 DataSet 基本相同。
3.自定义业务实体(Business Entity)
这是一种自定义类,用于表示各种业务实体类型。可以定义保存业务实体数据的字段,并定义将此数据向应用程序各层中公开的属性(getter/setter),或者进一步使用在该类中定义的字段来定义方法以封装简单的业务逻辑。
应当封装应用程序的功能的核心业务实体,而不是为每个表定义单独的业务实体。
优点:(1)可维护性,更改架构一般不会影响数据访问逻辑组件方法签名。(2)相对DataSet而言,有更好的性能。(3)编译期间提供类型安全检测。(4)代码易读。要访问自定义实体类中的数据,可以使用有类型的方法和属性。(5)自定义实体可以包含方法以封装简单的业务规则。(6)本地化验证。自定义实体类可以在其属性存取器(getter/setter)中执行简单的验证测试以检测无效的业务实体数据。(7)专用字段。可以隐藏不希望向调用程序公开的信息。
缺点:(1)需要编写并维护自定义DTO类。(2)自定义实体表示的是单个业务实体,而不是一个业务实体集合。要保存多个业务实体,调用应用程序必须创建一个数组或一个 .NET 集合。(3)必须在自定义实体中实现自己的序列化机制。可以使用属性来控制实体组件的序列化方式,也可以通过实现 ISerializable 接口来控制自己的序列化。(4)部署问题。必须在所有物理层部署包含自定义实体的程序集。(5)可扩展性问题。如果修改了数据库架构,则可能需要修改自定义实体类并重新部署程序集。
4.简单标量参数列表
根据需要传入的参数,传入一系列简单的标量值。
优点:(1)标量值本身支持序列化。(2)内存使用效率高,标量值只传递实际调用需要的数据。(3)更高的性能。(4)最明显的特点是简单方便。
缺点:(1)紧密耦合与维护。架构的更改可能需要修改方法签名,这会影响调用代码。(2)有可能存在进行多次单独的方法调用,这在分布式环境中会给性能带来很大影响。(3)难以表达复杂的数据关系。
当然,在实际的分布式应用系统中,会根据实际情况的要求,使用不同的DTO对象。
下面通过描述简单的分布式应用架构模型设计,来演示DTO对象在层与层之间的数据传递和交互:
References:
1. Angela Crocker, Andy Olsen, Edward Jezierski, Microsoft, 设计数据层组件并在层间传递数据, http://www.microsoft.com/china/msdn/archives/library/dnbda/html/BOAGag.asp