如果将业务实体实现为数据结构(如 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() public CustomerDataSet GetCustomer(string id) public string CreateCustomer(string name, public void UpdateCustomer(CustomerDataSet updatedCustomer) public void DeleteCustomer(string id) public DataSet GetCustomersWhoPurchasedProduct(int productID) | 
  如何使用 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 应用程序中编程应用样式表,请执行以下步骤:
- 导入 System.Xml.Xsl 命名空间,如以下代码所示。System.Xml.Xsl 命名空间包含 .NET Framework 类库中的 XSLT 转换类。
 using System.Xml.Xsl;
 
- 创建一个 XslTransform 对象,如以下代码所示: 
 XslTransform stylesheet = new XslTransform();
 
- 将所需样式表加载到 XslTransform 对象,如以下代码所示: 
 stylesheet.Load("MyStylesheet.xsl");
 
- 调用 XslTransform 对象的 Transform 方法,如以下代码所示。调用 Transform 方法指定 XML 源文档和结果文档的名称。 
 stylesheet.Transform(sourceDoc, resultDoc);
可以使用有类型的 DataSet 表示业务实体。创建有类型的 DataSet 的方法有多种:
- 从 Microsoft Visual Studio ®.NET 中的数据适配器创建
- 从 Visual Studio .NET 中的 XSD 架构文件创建
- 使用 XSD 架构定义工具 (xsd.exe) 从 .NET Framework 命令提示窗口创建
注意:也可以编程定义有类型的 DataSet,即从 DataSet 继承并定义方法、属性和嵌套类以表示该 DataSet 的结构。最简单的方法是使用以下过程之一创建一个有类型的 DataSet,然后将此有类型的 DataSet 类用作将来您自己的有类型的 DataSet 类的基础。使用数据适配器创建有类型的 DataSet
要使用数据适配器创建有类型的 DataSet,请执行以下步骤:
- 在 Visual Studio .NET 中,向您的窗体或组件添加一个数据适配器。在数据适配器的配置向导中,指定该数据适配器的连接信息。同时根据具体情况,为数据适配器的 Select、Insert、Update 和 Delete 命令指定 SQL 字符串或存储过程。
- 在组件设计器中,在数据适配器对象上单击鼠标右键,然后单击 Generate DataSet(生成 DataSet)。
- 在 Generate DataSet(生成 DataSet)对话框中,单击 New(新建),键入新 DataSet 类的名称,然后单击 OK(确定)。
- 为确认已创建该有类型的 DataSet,可以在解决方案资源管理器中单击 Show All Files(显示所有文件)按钮。展开 XSD 架构文件的节点,确认存在一个与 XSD 架构相关联的代码文件。该代码文件定义了新的有类型的 DataSet 类。
要使用 Visual Studio .NET 从 XSD 架构文件创建有类型的 DataSet,请执行以下步骤:
- 在 Visual Studio .NET中,创建一个新项目或打开一个现有项目。
- 为项目添加一个现有的 XSD 架构,或在组件设计器中创建一个新的 XSD 架构。
- 在解决方案资源管理器中,双击 XSD 架构文件,在组件设计器中查看该 XSD 架构。
- 在组件设计器中选择主 XSD 架构元素。
- 在 Schema(架构)菜单中,单击 Generate DataSet(生成 DataSet)。
- 为确认已创建该有类型的 DataSet,可以在解决方案资源管理器中单击 Show All Files(显示所有文件)按钮。展开 XSD 架构文件的节点,确认存在一个与 XSD 架构相关联的代码文件。该代码文件定义了新的有类型的 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 实体的状态 // 执行本地化处理的方法和属性 | 
如何表示业务实体组件中数据的集合和层次结构
以下示例显示了如何为 Order 业务实体定义自定义实体类。每个订单都包含许多订购项目,这些订购项目保存在 OrderEntity 类的一个 DataSet 中。
| public class OrderEntity // 专用字段,用于保存订单详细信息 // 公共属性,用于提供订单信息 // 公共属性,用于提供订单详细信息 // 附加方法,用于简化对订单详细信息的访问 // 附加属性,用于简化对订单详细信息的访问 | 
关于 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 类中产生业务实体相关事件:
| // 为所有业务实体事件定义公用事件类 // 定义一个代理,用于为业务实体相关事件指定签名 // 定义自定义实体类,它可以在业务实体状态改变时产生事件  // 专用字段,用于保存业务实体的状态 // 公共属性,用于提供业务实体的状态 // 必要时使用更多成员... | 
关于上述代码,请注意以下几点:
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 类 // 将 OrderEntity 对象序列化为名为“MyXmlOrderEntity.xml”的 XML 文件 | 
在 XML Web services 中序列化对象
以下代码示例显示了如何编写使用自定义实体对象的 XML Web services:
| namespace MyWebService // 使用 dalcOrder 获取指定订单 ID 的 OrderEntity 对象。 // 返回 OrderEntity 对象, 该对象将自动序列化。 [WebMethod] // 使用 dalcOrder 将 OrderEntity 对象的数据保存到数据库中。 | 
关于上述代码,请注意以下几点:
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")] [XmlAttribute(AttributeName="CustID")] [XmlElement(ElementName="Ordered")] public DataSet OrderDetails {...获取和设置代码,同前...} [XmlElement(ElementName="Shipped") // 必要时使用更多成员... | 
将 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 类 // 将 OrderEntity 对象序列化为名为“MySoapOrderEntity.xml”的 SOAP (XML) 文件 | 
  要对自定义实体组件使用 SOAP 序列化,必须使用 Serializable 属性注释您的实体类,如以下代码所示:
| [Serializable] public class OrderEntity { // 成员,同前 | 
如果要自定义序列化过程中生成的 SOAP 格式,实体类必须实现 ISerializable 接口。您必须提供一个 GetObjectData 方法供 SoapFormatter 在序列化过程中调用,并提供一个特殊构造函数供 SoapFormatter 在还原序列化过程中调用以重新创建对象。以下代码显示了 ISerializable 接口、GetObjectData 方法和特殊构造函数的使用:
| using System.Runtime.Serialization; // 用于 ISerializable 接口以及相关类型 // 还原序列化构造函数,由 SoapFormatter 在还原序列化过程中调用 | 
如何将业务实体组件序列化为二进制格式
以下代码示例显示了如何使用 BinaryFormatter 类将 OrderEntity 对象序列化为二进制格式。当使用 TCP 远程通道向或从 Remoting 服务器传递对象时,也会发生二进制序列化(隐式)。此外,为提高性能,您也可以在使用 HTTP 远程通道时指定二进制格式化。
| using System.Runtime.Serialization.Formatters.Binary; // 用于 BinaryFormatter 类 // 将 OrderEntity 对象序列化为名为“MyBinaryOrderEntity.dat”的二进制文件 | 
要对自定义实体对象使用二进制序列化,必须使用 Serializable 属性注释您的自定义实体类。要自定义序列化过程中生成的二进制格式,自定义实体类必须实现 ISerializable 接口。这两种方案中的详细代码与 SOAP 序列化的代码相同。
 
                     
                    
                 
                    
                 
                
 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号