Rovan

      一个犁牛半块田,收也凭天,荒也凭天, 清茶淡饭饱三餐,早也香甜,晚也香甜, 布衣得暖胜丝绵,长也可穿,短也可穿, 草舍茅屋有几间,行也安然,待也安然, 雨过天青驾小船,鱼在一边,酒在一边, 夜归儿女话灯前,今也有言,古也有言, 日上三竿我独眠,请是神仙,我是神仙.

首页 新随笔 联系 订阅 管理
业务实体组件中的安全性建议

  如果将业务实体实现为数据结构(如 XML 或 DataSet),则不需要实现安全性检查。然而,如果将业务实体实现为带有 CRUD 操作的自定义业务实体组件,请考虑以下建议:

  • 如果将实体提供给您不完全信任的业务过程,应在业务实体组件和数据访问逻辑组件中实现授权检查。然而,如果在这两个层次上都实现检查,可能会产生保持安全性策略同步的维护问题。
  • 业务实体组件不应处理通信安全性或数据加密,应把这些任务留给相应的数据访问逻辑组件。
  部署

  本节提供一些建议以帮助您确定如何部署数据访问逻辑组件和业务实体组件。

  部署数据访问逻辑组件

  部署数据访问逻辑组件的方法有两种:

  • 与业务过程对象一起部署数据访问逻辑组件。这种部署方法具有最佳的数据传输性能,还有一些额外的技术优势:
    • 事务处理可以在业务过程对象和数据访问逻辑组件之间无缝流动。然而,事务处理不能跨越远程通道无缝流动。在远程方案下,需要使用 DCOM 来实现事务处理。此外,如果业务过程与数据访问逻辑组件被防火墙分开,还需要打开这两个物理层之间的防火墙端口以启用 DTC 通信。
    • 一起部署业务过程对象和数据访问逻辑组件可以减少事务处理失败节点的数目。
    • 安全性环境自动在业务过程对象和数据访问逻辑组件之间流动,无需设置当事人对象。
  • 与用户界面代码一起部署数据访问逻辑组件。有时需要直接从 UI 组件和 UI 过程组件使用数据访问逻辑组件。为提高 Web 方案下的性能,可以与 UI 代码一起部署数据访问逻辑组件;这种部署方法可以使 UI 层充分利用数据读取器流以获得最佳性能。然而,在使用这种部署方法时必须牢记以下事项:
    • 不与 UI 代码一起部署数据访问逻辑组件的一个常见原因是防止通过 Web 领域直接对数据源进行网络访问。
    • 如果您的 Web 领域部署在 DMZ 环境中,则必须打开防火墙端口才能访问 SQL Server。如果使用 COM+ 事务处理,还必须为 DTC 通信打开其他的防火墙端口。
  部署业务实体

  应用程序的许多不同层都要使用业务实体。根据业务实体的实现方式,如果您的应用程序跨越各个物理层,则需要将业务实体部署到多个位置。下面列出了在不同实现方案中部署业务实体的方法:

  • 部署作为有类型的 DataSet 实现的业务实体。有类型的 DataSet 类必须由数据访问逻辑组件和调用应用程序访问。因此,建议在一个要部署在多个层的公共程序集中定义有类型的 DataSet 类。
  • 部署作为自定义业务实体组件实现的业务实体。根据数据访问逻辑组件中定义的方法签名,自定义实体类可能需要由数据访问逻辑组件访问。请遵循与有类型的 DataSet 相同的建议,即在一个要部署在多个层的公共程序集中定义自定义实体类。
  • 部署作为通用 DataSet 或 XML 字符串实现的业务实体。通用 DataSet 和 XML 字符串不表示单独的数据类型。以这两种格式实现的业务实体不存在部署问题。
  如何定义数据访问逻辑组件类

  以下代码示例定义一个名为 CustomerDALC 的类,它是用于 Customer 业务实体的数据访问逻辑组件类。CustomerDALC 类为 Customer 业务实体实现 CRUD 操作,并提供了其他方法为此对象封装业务逻辑。

public class CustomerDALC
{
private string conn_string;

public CustomerDALC()
{
// 从安全或加密的位置获取连接字符串
// 并将其分配给 conn_string
}

public CustomerDataSet GetCustomer(string id)
{
// 检索包含 Customer 数据的有类型的 DataSet
}

public string CreateCustomer(string name,
string address, string city, string state,
string zip)
{
// 根据传递给此方法的标量参数,在数据库中创建一个
// 新客户。
// 从此方法返回 customerID。
}

public void UpdateCustomer(CustomerDataSet updatedCustomer)
{
// 根据作为类型 CustomerDataSet 的参数发送的 Customer 数据,更新
// 数据库。
}

public void DeleteCustomer(string id)
{
// 删除具有指定 ID 的客户
}

public DataSet GetCustomersWhoPurchasedProduct(int productID)
{
// 使用通用 DataSet 检索客户,因为此方法
// 不需要检索与客户关联的全部信息
}
}

  如何使用 XML 表示数据的集合和层次结构

  以下示例显示了如何在 XML 文档中表示数据的集合和层次结构。该 XML 文档表示客户的一个订单;注意,元素 <OrderDetails> 包含一个该订单的详细信息集合。

<Order xmlns="urn:aUniqueNamespace">
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<OrderDate>1996-07-04</OrderDate>
<ShippedDate>1996-07-16</ShippedDate>
<OrderDetails>
<OrderDetail>
<ProductID>11</ProductID>
<UnitPrice>14.00</UnitPrice>
<Quantity>12</Quantity>
</OrderDetail>
<OrderDetail>
<ProductID>42</ProductID>
<UnitPrice>9.80</UnitPrice>
<Quantity>10</Quantity>
</OrderDetail>
<OrderDetail>
<ProductID>72</ProductID>
<UnitPrice>34.80</UnitPrice>
<Quantity>5</Quantity>
</OrderDetail>
</OrderDetails>
</Order>

 如何在 .NET 应用程序中编程应用样式表

  要在 .NET 应用程序中编程应用样式表,请执行以下步骤:

  1. 导入 System.Xml.Xsl 命名空间,如以下代码所示。System.Xml.Xsl 命名空间包含 .NET Framework 类库中的 XSLT 转换类。

    using System.Xml.Xsl;

  2. 创建一个 XslTransform 对象,如以下代码所示:
    XslTransform stylesheet = new XslTransform();

  3. 将所需样式表加载到 XslTransform 对象,如以下代码所示:
    stylesheet.Load("MyStylesheet.xsl");

  4. 调用 XslTransform 对象的 Transform 方法,如以下代码所示。调用 Transform 方法指定 XML 源文档和结果文档的名称。

    stylesheet.Transform(sourceDoc, resultDoc);
  如何创建有类型的 DataSet

  可以使用有类型的 DataSet 表示业务实体。创建有类型的 DataSet 的方法有多种:

  • 从 Microsoft Visual Studio ®.NET 中的数据适配器创建
  • 从 Visual Studio .NET 中的 XSD 架构文件创建
  • 使用 XSD 架构定义工具 (xsd.exe) 从 .NET Framework 命令提示窗口创建
注意:也可以编程定义有类型的 DataSet,即从 DataSet 继承并定义方法、属性和嵌套类以表示该 DataSet 的结构。最简单的方法是使用以下过程之一创建一个有类型的 DataSet,然后将此有类型的 DataSet 类用作将来您自己的有类型的 DataSet 类的基础。
  使用数据适配器创建有类型的 DataSet

  要使用数据适配器创建有类型的 DataSet,请执行以下步骤:

  1. 在 Visual Studio .NET 中,向您的窗体或组件添加一个数据适配器。在数据适配器的配置向导中,指定该数据适配器的连接信息。同时根据具体情况,为数据适配器的 Select、Insert、Update 和 Delete 命令指定 SQL 字符串或存储过程。
  2. 在组件设计器中,在数据适配器对象上单击鼠标右键,然后单击 Generate DataSet(生成 DataSet)。
  3. 在 Generate DataSet(生成 DataSet)对话框中,单击 New(新建),键入新 DataSet 类的名称,然后单击 OK(确定)。
  4. 为确认已创建该有类型的 DataSet,可以在解决方案资源管理器中单击 Show All Files(显示所有文件)按钮。展开 XSD 架构文件的节点,确认存在一个与 XSD 架构相关联的代码文件。该代码文件定义了新的有类型的 DataSet 类。
  从 XSD 架构文件创建有类型的 DataSet

  要使用 Visual Studio .NET 从 XSD 架构文件创建有类型的 DataSet,请执行以下步骤:

  1. 在 Visual Studio .NET中,创建一个新项目或打开一个现有项目。
  2. 为项目添加一个现有的 XSD 架构,或在组件设计器中创建一个新的 XSD 架构。
  3. 在解决方案资源管理器中,双击 XSD 架构文件,在组件设计器中查看该 XSD 架构。
  4. 在组件设计器中选择主 XSD 架构元素。
  5. 在 Schema(架构)菜单中,单击 Generate DataSet(生成 DataSet)。
  6. 为确认已创建该有类型的 DataSet,可以在解决方案资源管理器中单击 Show All Files(显示所有文件)按钮。展开 XSD 架构文件的节点,确认存在一个与 XSD 架构相关联的代码文件。该代码文件定义了新的有类型的 DataSet 类。
  使用 XSD 架构定义工具 (xsd.exe) 创建有类型的 DataSet

  XML 架构定义工具可以从 XSD 架构文件、XDR 架构文件或 XML 实例文档生成有类型的 DataSet。以下命令使用名为 XsdSchemaFile.xsd 的 XSD 架构文件,在当前目录中名为 XsdSchemaFile.cs 的 Visual C# 源文件中生成一个有类型的 DataSet:

  xsd /dataset /language:C# XsdSchemaFile.xsd

  如何定义业务实体组件

  以下示例显示了如何为 Product 业务实体定义自定义实体类:

public class ProductEntity
{
// 专用字段,用于保存 Product 实体的状态
private int productID;
private string productName;
private string quantityPerUnit;
private decimal unitPrice;
private short unitsInStock;
private short unitsOnOrder;
private short reorderLevel;

// 公共属性,用于公开 Product 实体的状态
public int ProductID
{
get { return productID; }
set { productID = value; }
}
public string ProductName
{
get { return productName; }
set { productName = value; }
}
public string QuantityPerUnit
{
get { return quantityPerUnit; }
set { quantityPerUnit = value; }
}
public decimal UnitPrice
{
get { return unitPrice; }
set { unitPrice = value; }
}
public short UnitsInStock
{
get { return unitsInStock; }
set { unitsInStock = value; }
}
public short UnitsOnOrder
{
get { return unitsOnOrder; }
set { unitsOnOrder = value; }
}
public short ReorderLevel
{
get { return reorderLevel; }
set { reorderLevel = value; }
}

// 执行本地化处理的方法和属性
public void IncreaseUnitPriceBy(decimal amount)
{
unitPrice += amount;
}
public short UnitsAboveReorderLevel
{
get { return (short)(unitsInStock - reorderLevel); }
}
public string StockStatus
{
get
{
return "库存:"+ unitsInStock + ",订购:" + unitsOnOrder;
}
}
}

  如何表示业务实体组件中数据的集合和层次结构

  以下示例显示了如何为 Order 业务实体定义自定义实体类。每个订单都包含许多订购项目,这些订购项目保存在 OrderEntity 类的一个 DataSet 中。

public class OrderEntity
{
// 专用字段,用于保存订单信息
private int orderID;
private string customerID;
private DateTime orderDate;
private DateTime shippedDate;

// 专用字段,用于保存订单详细信息
private DataSet orderDetails;

// 公共属性,用于提供订单信息
public int OrderID
{
get { return orderID; }
set { orderID = value; }
}
public string CustomerID
{
get { return customerID; }
set { customerID = value; }
}
public DateTime OrderDate
{
get { return orderDate; }
set { orderDate = value; }
}
public DateTime ShippedDate
{
get { return shippedDate; }
set { shippedDate = value; }
}

// 公共属性,用于提供订单详细信息
public DataSet OrderDetails
{
get { return orderDetails; }
set { orderDetails = value; }
}

// 附加方法,用于简化对订单详细信息的访问
public bool IsProductOrdered(int productID)
{
// 必须在 DataTable 中定义主关键字列
DataRow row = orderDetails.Tables[0].Rows.Find(productID);

if (row != null)
return true;
else
return false;
}

// 附加属性,用于简化对订单详细信息的访问
public int NumberOfOrderItems
{
get
{
return orderDetails.Tables[0].Rows.Count;
}
}
}

  关于 OrderEntity 类,请注意以下几点:

  • 该类包含用于保存有关订单的信息的专用字段。还有一个专用 DataSet 字段,用于保存订单的其他详细信息。数据访问逻辑组件将在创建 OrderEntity 对象时填充所有这些字段。
  • 该类包含用于提供有关订单的信息的公共属性。此外还有一个用于提供该 DataSet 的属性,以便使调用应用程序能够访问订单详细信息。
  • 该类包含一个附加方法和一个附加属性,用于简化对订单详细信息的访问:
    • IsProductOrdered 方法接收一个 ProductID 参数,并返回一个布尔值以表明该产品是否出现在订单中。
    • NumberOfOrderItems 属性表明订单中的订购行数目。
  如何将业务实体组件绑定到用户界面控件

  可以将用户界面控件绑定到 Windows 窗体和 ASP.NET 应用程序中的自定义实体。有两种可能的方案:

  • 在用户界面控件上绑定单个业务实体。以下代码示例显示了如何从 OrderDALC 对象获取一个 OrderEntity 对象并将其绑定到 Windows 窗体的控件上。当用户更改这些控件中的值时,基础 OrderEntity 对象中的数据也将自动更改。 // 创建 OrderDALC 对象。

    OrderDALC dalcOrder = new OrderDALC();

    // 使用 dalcOrder 为订单 ID 10248 获取一个 OrderEntity 对象。
    // 此代码假设 OrderDALC 类有一个名为 GetOrder() 的方法,
    // 该方法为特定订单 ID 返回一个 OrderEntity 对象。
    OrderEntity order = dalcOrder.GetOrder(10248);

    // 将 OrderEntity 的 OrderID 属性绑定到 TextBox 控件。
    textBox1.DataBindings.Add("Text", order, "OrderID");

    // 将 OrderEntity 的 CustomerID 属性绑定到另一个 TextBox 控件。
    control.
    textBox2.DataBindings.Add("Text", order, "CustomerID");

    // 将 OrderEntity 的 OrderDate 属性绑定到 DatePicker 控件。
    dateTimePicker1.DataBindings.Add("Value", order, "OrderDate");

    // 将 OrderEntity 的 ShippedDate 属性绑定到另一个 DatePicker 控件。
    dateTimePicker2.DataBindings.Add("Value", order, "ShippedDate");

    // 将 OrderEntity 的 OrderDetails DataSet 绑定到 DataGrid 控件。
    // DataGrid 分别用网格中的一行显示 DataSet 的各个 DataRow。
    dataGrid1.DataSource = order.OrderDetails.Tables[0].DefaultView;

    准备好后,您可以将修改后的 OrderEntity 对象传递给 OrderDALC,以便将数据保存到数据库中,如以下代码所示。

    // 通过 dalcOrder 将 OrderEntity 对象保存到数据库中。
    // 此代码假设 OrderDALC 类有一个名为 UpdateOrder() 的方法,
    // 该方法接收一个 OrderEntity 参数,并更新数据库中的相应项
    dalcOrder.UpdateOrder(order);

  • 将业务实体集合绑定到 DataGrid 控件。以下代码示例显示了如何从 OrderDALC 获取一个 OrderEntity 对象数组并将其绑定到 Windows 窗体的 DataGrid 控件。DataGrid 分别用网格中的一行显示每个数组元素(即每个 OrderEntity 对象)。 // 创建 OrderDALC 对象。
    OrderDALC dalcOrder = new OrderDALC();

    // 使用 dalcOrder 获取客户“VINET”的 OrderEntity 对象数组。
    // 此代码假设 OrderDALC 类有一个名为
    GetOrdersForCustomer(),
    // 的方法,该方法返回特定客户的 OrderEntity 对象数组。
    OrderEntity[] orderEntities = dalcOrder.GetOrdersForCustomer("VINET");

    // 将该数组绑定到 DataGrid 控件。
    dataGrid1.DataSource = orderEntities;


    准备好后,您可以将修改后的数组传递给 OrderDALC,以便将数据保存到数据库中,如以下代码所示:

    // 通过 dalcOrder 将 OrderEntity 对象保存到数据库中。
    // 此代码假设 OrderDALC 类有一个名为 UpdateOrder() 的方法,该方法获取
    // 一个 OrderEntity 对象数组,并更新数据库中的相应项。
    dalcOrder.UpdateOrders(orderEntities);

  如何在业务实体组件中提供事件

  自定义实体可以在业务实体状态修改时产生事件。这些事件可用于获得丰富的客户端用户界面设计,因为这使得无论数据显示在哪里都可以对其进行刷新。以下代码示例显示了如何在 OrderEntity 类中产生业务实体相关事件:

// 为所有业务实体事件定义公用事件类
public class EntityEventArgs : EventArgs
{
// 定义事件成员,用于提供有关事件的信息
}

// 定义一个代理,用于为业务实体相关事件指定签名
public delegate void EntityEventHandler(Object source, EntityEventArgs e);

// 定义自定义实体类,它可以在业务实体状态改变时产生事件
public class OrderEntity
{
// 定义业务实体状态改变的“before”事件和“after”事件
public event EntityEventHandler BeforeChange, AfterChange;

// 专用字段,用于保存业务实体的状态
private int orderID;
private int customerID;
private DateTime orderDate;
private DateTime shippedDate;
private DataSet orderDetails;

// 公共属性,用于提供业务实体的状态
public int OrderID
{
get { return orderID; }
set
{
BeforeChange(this, new EntityEventArgs()); // 产生“before”事件
orderID = value;
AfterChange(this, new EntityEventArgs()); // 产生“after”事件
}
}
public int CustomerID
{
get { return customerID; }
set
{
BeforeChange(this, new EntityEventArgs()); // 产生“before”事件
customerID = value;
AfterChange(this, new EntityEventArgs()); // 产生“after”事件
}
}
public DateTime OrderDate
{
get { return orderDate; }
set
{
BeforeChange(this, new EntityEventArgs()); // 产生“before”事件
orderDate = value;
AfterChange(this, new EntityEventArgs()); // 产生“after”事件
}
}
public DateTime ShippedDate
{
get { return shippedDate; }
set
{
BeforeChange(this, new EntityEventArgs()); // 产生“before”事件
shippedDate = value;
AfterChange(this, new EntityEventArgs()); // 产生“after”事件
}
}

// 必要时使用更多成员...
}

  关于上述代码,请注意以下几点:

  EntityEvent 类提供有关业务实体相关事件的信息。EntityEventHandler 代理为自定义实体类产生的所有业务实体相关事件指定签名。该代理签名遵循所建议的 .NET Framework 事件处理程序代理的原则。

  OrderEntity 类定义了两个名为 BeforeChange 和 AfterChange 的事件。

  OrderEntity 中的属性设置器在业务实体状态改变前产生一个 BeforeChange 事件,在业务实体状态改变后产生一个 AfterChange 事件。

 

  如何将业务实体组件序列化为 XML 格式

  本节讨论以下问题:

  使用 XmlSerializer 序列化自定义实体对象

  XML Web services 中对象的 XML 序列化

  序列化自定义实体对象的默认 XML 格式

  控制序列化自定义实体对象的 XML 格式

  使用 XmlSerializer 序列化自定义实体对象

  以下代码示例显示了如何使用 XmlSerializer 类将 OrderEntity 对象序列化为 XML 格式:

using System.Xml.Serialization; // 此命名空间包含 XmlSerializer 类
...
// 创建一个 XmlSerializer 对象,用于序列化 OrderEntity 类型的对象
XmlSerializer serializer = new XmlSerializer(typeof(OrderEntity));

// 将 OrderEntity 对象序列化为名为“MyXmlOrderEntity.xml”的 XML 文件
TextWriter writer = new StreamWriter("MyXmlOrderEntity.xml");
serializer.Serialize(writer, order);
writer.Close();

  在 XML Web services 中序列化对象

  以下代码示例显示了如何编写使用自定义实体对象的 XML Web services:

namespace MyWebService
{
[WebService(Namespace="urn:MyWebServiceNamespace")]
public class OrderWS : System.Web.Services.WebService
{
[WebMethod]
public OrderEntity GetOrder(int orderID)
{
// 创建 OrderDALC 对象
OrderDALC dalcOrder = new OrderDALC();

// 使用 dalcOrder 获取指定订单 ID 的 OrderEntity 对象。
// 此代码假设 OrderDALC 类有一个名为 GetOrder 的方法,
// 该方法获取一个订单 ID 作为参数,并返回一个 OrderEntity 对象,
// 其中包含该订单的所有数据。
OrderEntity order = dalcOrder.GetOrder(10248);

// 返回 OrderEntity 对象, 该对象将自动序列化。
return order;
}

[WebMethod]
public void UpdateOrder(OrderEntity order)
{
// 创建 OrderDALC 对象。
OrderDALC dalcOrder = new OrderDALC();

// 使用 dalcOrder 将 OrderEntity 对象的数据保存到数据库中。
// 此代码假设 OrderDALC 类有一个名为 UpdateOrder 的方法,
// 该方法接收一个 OrderEntity 对象并将数据保存到数据库中。
dalcOrder.UpdateOrder(order);
}

  关于上述代码,请注意以下几点:

  GetOrder 方法接收一个订单 ID 作为参数,并返回包含该订单的数据的 OrderEntity 对象。

  UpdateOrder 方法接收一个 OrderEntity 对象并将该对象的数据保存到数据库中。

  如果客户端应用程序调用 GetOrder 和 UpdateOrder 方法,OrderEntity 对象将为该方法调用自动序列化为 XML 格式。

 

  序列化自定义实体对象的默认 XML 格式

  以下 XML 文档显示了 OrderEntity 对象的默认 XML 序列化格式:

<?xml version="1.0" encoding="utf-8"?>
<OrderEntity xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OrderID>10248</OrderID>
<CustomerID>VINET</CustomerID>
<OrderDate>1996-07-04T00:00:00.0000000+01:00</OrderDate>
<OrderDetails> ... see below ... </OrderDetails>
<ShippedDate>1996-07-16T00:00:00.0000000+01:00</ShippedDate>
</OrderEntity>

  上述文档说明了 XML 序列化的默认规则:

  该 XML 文档的根元素与类名称 OrderEntity 相同。

  OrderEntity 对象中的每个公共属性(及字段)都被序列化为具有相同名称的元素。

 

  OrderEntity 类中的 OrderDetails 属性是一个 DataSet,DataSet 提供了内置的 XML 序列化支持。OrderDetails DataSet 的序列化结果如下:

<OrderDetails>
<xs:schema id="NewDataSet" xmlns=""
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="en-
UK">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="OrderDetails">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderID" type="xs:int" minOccurs="0" />
<xs:element name="ProductID" type="xs:int" minOccurs="0" />
<xs:element name="UnitPrice" type="xs:decimal" minOccurs="0"
/>
<xs:element name="Quantity" type="xs:short" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet>
<OrderDetails diffgr:id="OrderDetails1" msdata:rowOrder="0"
diffgr:hasChanges="inserted">
<OrderID>10248</OrderID>
<ProductID>11</ProductID>
<UnitPrice>14</UnitPrice>
<Quantity>12</Quantity>
</OrderDetails>
<OrderDetails diffgr:id="OrderDetails2" msdata:rowOrder="1"
diffgr:hasChanges="inserted">
<OrderID>10248</OrderID>
<ProductID>42</ProductID>
<UnitPrice>9.8</UnitPrice>
<Quantity>10</Quantity>
</OrderDetails>
<OrderDetails diffgr:id="OrderDetails3" msdata:rowOrder="2"
diffgr:hasChanges="inserted">
<OrderID>10248</OrderID>
<ProductID>72</ProductID>
<UnitPrice>34.8</UnitPrice>
<Quantity>5</Quantity>
</OrderDetails>
</NewDataSet>
</diffgr:diffgram>
</OrderDetails>

  关于 DataSet 的序列化,请注意以下几点:

  <xs:schema> 段描述了 DataSet 的结构,包括表、列名称和列类型。

  <xs:diffgram> 段包含该 DataSet 的数据。每个 <OrderDetails> 元素表示该 DataSet 中 OrderDetails 表中的单独一行。

 

  控制序列化自定义实体对象的 XML 格式

  您可以在自定义实体类中使用 .NET 属性来控制属性和字段序列化为 XML 的方式。请考虑以下修订后的 OrderEntity 类:

[XmlRoot(ElementName="Order", Namespace="urn:MyNamespace")]
public class OrderEntity
{
[XmlAttribute(AttributeName="ID")]
public int OrderID {...获取和设置代码,同前...}

[XmlAttribute(AttributeName="CustID")]
public string CustomerID {...获取和设置代码,同前...}

[XmlElement(ElementName="Ordered")]
public DateTime OrderDate {...获取和设置代码,同前...}

public DataSet OrderDetails {...获取和设置代码,同前...}

[XmlElement(ElementName="Shipped")
public DateTime ShippedDate {...获取和设置代码,同前...}

// 必要时使用更多成员...
}

  将 OrderEntity 对象序列化为 XML 后,其格式如下:

 

<?xml version="1.0" encoding="utf-8" ?>
<Order ID="10248"
CustID="VINET"
xmlns="urn:MyNamespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Ordered>1996-07-04T00:00:00.0000000+01:00</Ordered>
<OrderDetails>...详细代码同前...</OrderDetails>
<Shipped>1996-07-16T00:00:00.0000000+01:00</Shipped>
</Order>

  如何将业务实体组件序列化为 SOAP 格式

  以下代码示例显示了如何使用 SoapFormatter 类将 OrderEntity 对象序列化为 SOAP 格式。当使用 SOAP 协议向或从 XML Web services 传递对象,或者当使用 HTTP 远程通道向或从 Remoting 服务器传递对象时,也会发生 SOAP 序列化(隐式)。此外,您也可以在使用 TCP 远程通道时指定 SOAP 格式化。

using System.Runtime.Serialization.Formatters.Soap; // 用于 SoapFormatter 类
...
// 创建 SoapFormatter 对象,用于序列化 OrderEntity 类型的对象
SoapFormatter formatter = new SoapFormatter();

// 将 OrderEntity 对象序列化为名为“MySoapOrderEntity.xml”的 SOAP (XML) 文件
FileStream stream = File.Create("MySoapOrderEntity.xml");
formatter.Serialize(stream, order);
stream.Close();

  要对自定义实体组件使用 SOAP 序列化,必须使用 Serializable 属性注释您的实体类,如以下代码所示:

[Serializable]
public class OrderEntity
{
// 成员,同前

  如果要自定义序列化过程中生成的 SOAP 格式,实体类必须实现 ISerializable 接口。您必须提供一个 GetObjectData 方法供 SoapFormatter 在序列化过程中调用,并提供一个特殊构造函数供 SoapFormatter 在还原序列化过程中调用以重新创建对象。以下代码显示了 ISerializable 接口、GetObjectData 方法和特殊构造函数的使用:

using System.Runtime.Serialization; // 用于 ISerializable 接口以及相关类型
...
[Serializable]
public class OrderEntity : ISerializable
{
// 序列化函数,由 SoapFormatter 在序列化过程中调用
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext
ctxt)
{
// 向 SerializationInfo 对象中添加每个字段
info.AddValue("OrderID", orderID);
// 必要时使用更多代码...
}

// 还原序列化构造函数,由 SoapFormatter 在还原序列化过程中调用
public OrderEntity(SerializationInfo info, StreamingContext ctxt)
{
// 从 SerializationInfo 对象中还原序列化出各个 OrderEntity 字段
orderID = (int)info.GetValue("OrderID", typeof(int));
// 必要时使用更多代码...
}

// 其他成员,同前...
}

  如何将业务实体组件序列化为二进制格式

  以下代码示例显示了如何使用 BinaryFormatter 类将 OrderEntity 对象序列化为二进制格式。当使用 TCP 远程通道向或从 Remoting 服务器传递对象时,也会发生二进制序列化(隐式)。此外,为提高性能,您也可以在使用 HTTP 远程通道时指定二进制格式化。

using System.Runtime.Serialization.Formatters.Binary; // 用于 BinaryFormatter 类
...
// 创建 BinaryFormatter 对象,用于序列化 OrderEntity 类型的对象
BinaryFormatter formatter = new BinaryFormatter();

// 将 OrderEntity 对象序列化为名为“MyBinaryOrderEntity.dat”的二进制文件
FileStream stream = File.Create("MyBinaryOrderEntity.dat");
formatter.Serialize(stream, order);
stream.Close();

  要对自定义实体对象使用二进制序列化,必须使用 Serializable 属性注释您的自定义实体类。要自定义序列化过程中生成的二进制格式,自定义实体类必须实现 ISerializable 接口。这两种方案中的详细代码与 SOAP 序列化的代码相同。

posted on 2006-07-06 16:59  Ruxuan  阅读(453)  评论(0)    收藏  举报