轻松玩转Typed DataSet, Part II

轻松玩转Typed DataSet, Part II

 

Written by: Rickie Lee

Dec. 08, 2004

 

本文继续前面《轻松玩转Typed DataSet, Part I》,这里演练如何通过批注(Annotations)来定制类型化 DataSet,并调用定制的Typed DataSet

 

三、通过批注(Annotations)来定制类型化 DataSet

批注使您能够在不修改基础架构的情况下修改类型化 DataSet 中元素的名称。如果修改基础架构中元素的名称,则会使类型化 DataSet 引用不存在于数据源中的对象,并且会丢失对存在于数据源中的对象的引用。

利用批注,您可以使用更有意义的名称来自定义类型化 DataSet 中对象的名称,从而使代码更易于阅读,类型化 DataSet 更易于为客户端使用,同时保持基础架构不变。

VS.Net IDE默认的DataSet窗口切换到XML窗口。

1. 默认创建的VS.Net IDE自动生成的Orders table的架构元素

<xs:element name="Orders">

<xs:complexType>

         <xs:sequence>

         <xs:element name="OrderID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:int" />

         <xs:element name="CustomerID" type="xs:string" minOccurs="0" />

         <xs:element name="EmployeeID" type="xs:int" minOccurs="0" />

         <xs:element name="OrderDate" type="xs:dateTime" minOccurs="0" />

         <xs:element name="RequiredDate" type="xs:dateTime" minOccurs="0" />

         <xs:element name="ShippedDate" type="xs:dateTime" minOccurs="0" />

         <xs:element name="ShipVia" type="xs:int" minOccurs="0" />

         <xs:element name="Freight" type="xs:decimal" minOccurs="0" />

         <xs:element name="ShipName" type="xs:string" minOccurs="0" />

         <xs:element name="ShipAddress" type="xs:string" minOccurs="0" />

         <xs:element name="ShipCity" type="xs:string" minOccurs="0" />

         <xs:element name="ShipRegion" type="xs:string" minOccurs="0" />

         <xs:element name="ShipPostalCode" type="xs:string" minOccurs="0" />

         <xs:element name="ShipCountry" type="xs:string" minOccurs="0" />

         </xs:sequence>

</xs:complexType>

</xs:element>

上述XML Schema会生成OrdersRow这一对象名称OrderDataSet.OrdersRow,还有一个名为OrdersDataRowCollection ClassOrderDataSet.Orders)。

 

通过批注架构并标识 DataRow DataRowCollection 对象的新名称,使上述对象名称更有意义。

首先需要在schema header中增加namespace引用,允许定制元素属性,如下所示:

<xs:schema id="AnnotationTypedDataset" targetNamespace="http://tempuri.org/AnnotationTypedDataset.xsd"

          elementFormDefault="qualified" attributeFormDefault="qualified" xmlns="http://tempuri.org/AnnotationTypedDataset.xsd"

          xmlns:mstns="http://tempuri.org/AnnotationTypedDataset.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"

         xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:codegen="urn:schemas-microsoft-com:xml-msprop">

 

下面是上一架构的批注版本:

<xs:element name="Orders" codegen:typedName="Order" codegen:typedPlural="Orders">

<xs:complexType>

         <xs:sequence>

         <xs:element name="OrderID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:int" />

         <xs:element name="CustomerID" type="xs:string" minOccurs="0" />

         <xs:element name="EmployeeID" type="xs:int" minOccurs="0" />

         <xs:element name="OrderDate" type="xs:dateTime" minOccurs="0" />

         <xs:element name="RequiredDate" type="xs:dateTime" minOccurs="0" />

         <xs:element name="ShippedDate" type="xs:dateTime" minOccurs="0" />

         <xs:element name="ShipVia" type="xs:int" minOccurs="0" />

         <xs:element name="Freight" type="xs:decimal" minOccurs="0" />

         <xs:element name="ShipName" type="xs:string" minOccurs="0" />

         <xs:element name="ShipAddress" type="xs:string" minOccurs="0" />

         <xs:element name="ShipCity" type="xs:string" minOccurs="0" />

         <xs:element name="ShipRegion" type="xs:string" minOccurs="0" />

         <xs:element name="ShipPostalCode" type="xs:string" minOccurs="0" />

         <xs:element name="ShipCountry" type="xs:string" minOccurs="0" />

         </xs:sequence>

</xs:complexType>

</xs:element>

Order的值指定为 typedName 将生成 DataRow 对象名称 Order。将 Orders 的值指定为 typedPlural 则会保留 DataRowCollection 名称 Orders

下表显示可用的批注(From MSDN):

批注

说明

typedName

对象的名称。

typedPlural

对象集合的名称。

typedParent

对象在父关系中被引用时的名称。

typedChildren

用于从子关系中返回对象的方法的名称。

nullValue

如果基础值为 DBNull,则为值。有关 nullValue 批注的信息,请参见下表。默认为 _throw

 

下表显示可为 nullValue 批注指定的值FROM MSDN:

nullValue

说明

替换值

指定要返回的值。所返回的值必须匹配该元素的类型。例如,使用 nullValue="0" 可为空整数字段返回 0

_throw

引发异常。这是默认值。

_null

如果遇到基元类型,则返回空引用或引发异常。

_empty

对于字符串返回 String.Empty;否则,返回从空构造函数创建的对象。如果遇到基元类型,则引发异常。

 

下面是OrderDetails架构的批注版本:

<xs:element name="OrderDetails" codegen:typedName="OrderDetail" codegen:typedPlural="OrderDetails">

<xs:complexType>

         <xs:sequence>

         <xs:element name="OrderID" type="xs:int" />

         <xs:element name="ProductID" type="xs:int" />

         <xs:element name="UnitPrice" type="xs:decimal" />

         <xs:element name="Quantity" type="xs:short" />

         <xs:element name="Discount" type="xs:float" />

         </xs:sequence>

</xs:complexType>

</xs:element>

 

通过typedParenttypedChildren属性更改Order/OrderDetails对象的引用方法:

<xs:keyref name="OrdertoOrderDetails" refer="AnnotationTypedDatasetKey1" codegen:typedParent="Order" codegen:typedChildren="GetOrderDetails">

          <xs:selector xpath=".//mstns:OrderDetails" />

          <xs:field xpath="mstns:OrderID" />

</xs:keyref>

 

这样Order对象就产生一个GetOrderDetails()方法,沿着Relationship向下导航到OrderDetail对象,OrderDetails对象生成一个Order()方法,沿着Relationship向上导航到Order对象。

 

四、调用定制的Typed DataSet

如下是调用上述通过Annotation定制的Typed DataSetCode snippet如下所示:

AnnotationTypedDataset theOrderDS = new AnnotationTypedDataset();

string strSelectOrders = "Select  * From Orders ";

strSelectOrders += "Select * From [Order Details]";

SqlHelper.FillDataset(connStr, CommandType.Text, strSelectOrders, theOrderDS, new string[] {"Orders", "OrderDetails"});

 

StringBuilder strResults = new StringBuilder();

 

foreach(AnnotationTypedDataset.Order theOrder in theOrderDS.Orders)

{

         strResults.Append(theOrder.OrderID.ToString() + " "

                  + theOrder.CustomerID.ToString() + " "

                  + theOrder.EmployeeID.ToString() + Environment.NewLine);

         strResults.Append("Order Details: ");

         strResults.Append(theOrder.GetChildRows("OrdertoOrderDetails").Length.ToString() + " ");

         strResults.Append(theOrder.GetOrderDetails().Length.ToString());

         strResults.Append(Environment.NewLine);

}

 

txtResults.Text = strResults.ToString();

 

代码比较简单,上述代码调用了SqlHelper ClassMicrosoft Data Access Application Block)的FillDataset方法,来完成DataSet的填充。与调用默认的Typed DataSet代码相比较有细微差别。

 

Any questions or errors, please leave comments below. Thanks.

 

References:

1. MSDN

2. Rickie, 轻松玩转Typed DataSet, Part I

 

posted @ 2004-12-09 01:16  Rickie  阅读(2343)  评论(5编辑  收藏  举报