注意,DataRow类型是不能序列化的。
在WCF中,还可以使用DataTable和DataSet的类型安全的子类。书中也给出了相应的例子。然而,WCF的非常好的实践则是避免使用DataTable和DataSet,以及使用DataTable和DataSet的类型安全的子类。书中阐释了原因:
“对于WCF的客户端与服务而言,虽然可以通过ADO.NET和Visual Studio工具使用DataSet、DataTable以及它们的类型安全的派生对象,但这种方式过于繁琐。而且,这些数据访问类型都是特定的.NET类型。在序列化时,它们生成的数据契约样式过于复杂,很难与其它平台进行交互。在服务契约中使用数据表或者数据集还存在一个缺陷,那就是它可能暴露内部的数据结构。同时,将来对数据库样式的修改会影响到客户端。虽然在应用程序内部可以传递数据表,但如果是跨越应用程序或公有的服务边界发送数据表,却并非一个好的主意。通常情况下,更好的做法是暴露数据的操作而非数据本身。”
最好的做法是将DataTable转换为数组类型。书中提供了DataTableHelper类,可以帮助将DataTable转换为数组类型。
泛型
非常遗憾,我们并不能在数据契约中定义泛型。但是,WCF使用了一个折中的办法,使得我们可以在服务端照常使用泛型,但在生成的数据契约定义时,泛型会被具体的类型所取代,重命名的格式为:
<原有名>Of<类型参数名><哈希值>
WCF还支持将自定义类型作为泛型参数。此外,还可以通过数据契约的Name属性为导出的数据契约指定不同的名字。例如,如下的服务端数据契约:
导出的数据契约为:[DataContract] class SomeClass {...} [DataContract(Name = "MyClass")] class MyClass<T> {...} [OperationContract] void MyMethod(MyClass<SomeClass> obj);
集合[DataContract] class SomeClass {...} [DataContract] class MyClass {...} [OperationContract] void MyMethod(MyClass obj);
WCF支持泛型集合、定制集合,但与传统的.NET编程不一样,WCF对集合的操作存在许多约束。对于这些约束,本书描述得非常清楚。本文不再赘述。