XML Bulk Load和Updategrams,这两种客户端技术使用带有注解的大纲指定XML文档内容和数据库的表之间的映射;OpenXML是一种服务器端技术,它允许你在XML文档上定义关系视图, 有了OpenXML的关系视图,你就能使用T-SQL代码查询XML文档中的数据并把结果存储在你的SQL Server数据库中。
这三种技术中的每一种都是为特定的目的设计的。XML Bulk Load把来自 很大的XML文档的数据存储在SQL Server中;Updategrams执行SQL Server数据的优化更新(优 化更新是没有锁(lock)的更新,在这种更新中系统检测是否有其它用户在原来读取数据后改 变了它);OpenXML提供了人们熟悉的XML数据关系访问方法。
在这三种技术中,OpenXML是最灵活的,因为它提供了一个编程模型(T-SQL), 在把XML数据存储在SQL Server数据库之前,你可以使用这种编程模型在XML数据上编写业务规 则或执行计算逻辑。但是,由于OpenXML是一种基于服务器的技术,如果你频繁的使用它或者有 大量的文档,它会降低SQL Server的性能。不过,如果你采用了微软.NET框架组件,你就可以 使用ADO.NET的数据集绕开这些性能和可伸缩性方面的限制,ADO.NET数据集赋予你一个强大的 技术–为把XML数据存储在SQL Server包含了一个完整的编程模型。
数据集、数据表和XML映射
你可以使用数据集简单地从SQL Server中生成XML查询结果。通过提供一种可以在客户端和 中间层计算机上使用的关系数据缓存(cache),数据集能够载入和维护多种数据源(包括SQL Server、其它的关系型数据库和XML)中的数据。
当你从XML文档中载入一个数据集的时候,该数据集必须把存储在层次XML表现 (representation)中的数据映射成数据集的关系表现。例如,如果你的XML文档包含一个 Order元素列表,而它又有一个作为子元素的嵌套的LineItem元素,那么通常这个文档被映射成 关系表现中的Orders和LineItems数据表。这种映射的目的与OpenXML使用Xpath查询构造XML文 档上的关系视图的方法的目的是一样的。但是与使用Xpath规范不同,数据集有自己的映射数据 的方式。
数据集使用XML大纲定义(XSD)大纲把数据从XML文档映射到数据集的关系数据缓存中。数 据集为你提供了指定映射XML数据的大纲的两种方法。首先,你可以引用一个定义了XML文档中 使用的元素,属性和关系的XSD大纲。另一种方法是,你可以直接从文档的结构中推理大纲。换 句话说,数据集可以通过检查XML文档的结构和内容建立大纲。
当你引用XSD大纲的时候,数据集使用这个大纲中定义的元素、属性与元素之间的关系来构 造关系数据缓存中的数据表、数据列和数据关系,你可以使用这个数据缓存存储被映射的XML数 据。我谈到关系数据缓存中的结构或大纲的时候,一般把它称为数据缓存的形式。当数据集处 理大纲的时候,它会应用一组规则,这种规则与映射大纲中没有指定注解时Updategrams 和XML Bulk Load使用的默认映射规则相似,数据集使用这种规则建立数据集用于存储被映射的XML数 据的表。数据集的映射规则概述如下:
◆复合元素–即包含其它元素或属性的元素–被映射成表。
◆属性和简单值(simple-valued)子元素–只包含数据,不包含其它元素或属性的元素– 被映射成列。
◆数据类型从XSD类型映射为.NET类型。
推理(Inference)是一种快速、方便的把XML文档载入数据集的方法。表、列和关系都是” 自我测量”(introspection)自动建立的,”自我测量”是数据集检查XML文档的结构和内容的过 程。尽管使用推理明显减少了你的编程负担,但是它也给你的实现带来了不可预测性,因为对 XML文档的很小的改动可能引起数据集建立不同形式的表。这些形式的改变可能引起你的应用程 序意外中断。因此,我推荐你一般为应用程序引用一个大纲,建立原型的时候限制推理的使用 。
现在让我们看一看如何使用大纲建立一个可用于更新SQL Server数据库的客户端数据集数据 缓存的例子。
映射XML订单
假定你在编写一个接受用户订单的应用程序,订单是XML格式的,它的XSD 大纲如图1定义。该大纲定义了三种复合类型,分别提供订单的客户数据、订单数据和线性数据 项。一个顶层Customer元素定义了XML文档的根。这个封闭的系统定义了元素之间的关系: Order元素包含了一个LineItem元素,Customer元素包含一个Order元素。图2显示了符合图1定 义的大纲的一个XML文档实例。
图1:XSD大纲
以下是引用片段: <?xml version=”1.0″ encoding=”utf-8″?> <xs:schema targetNamespace=”urn:Sep2003Example” elementFormDefault=”qualified”;> <xs:complexType name=”OrderType”> <xs:sequence> <xs:element name=”OrderID” type=”xs:integer” /> <xs:element name=”LineItem” type=”LineItemType” /> </xs:sequence> </xs:complexType> < xs:complexType name=”LineItemType”> <xs:sequence> <xs:element name=”ProductID” type=”xs:int” /> <xs:element name=”Quantity” type=”xs:int” / > <xs:element name=”UnitPrice” type=”xs:decimal” /> </xs:sequence> </xs:complexType> <xs:complexType name=”CustomerType”> <xs:sequence> <xs:element name=”CustomerID” type=”xs:string” /> <xs:element name=”Order” type=”OrderType” /> </xs:sequence> </xs:complexType> <xs:element name=”Customer” type=”CustomerType”> </xs:element> </xs:schema> |
图2:一个XML文档示例
以下是引用片段: <?xml version=”1.0″ ?> <Customer > < CustomerID>ALFKI</CustomerID> <PO>9572658</PO> <Address> <Street >One Main Street</Street> <City>Anywhere</City> <State>NJ</State> <Zip>08080</Zip> </Address> <Order> <OrderID>10966</OrderID > <LineItem> <ProductID>37</ProductID> <UnitPrice>26.50 </UnitPrice> <Quantity>8</Quantity> <Description>Gravad lax </Description> </LineItem> <LineItem> <ProductID>56 </ProductID> <UnitPrice>38.00</UnitPrice> <Quantity>12</Quantity> <Description>Gnocchi di nonna Alice</Description> </LineItem> </Order> </Customer> |
列表1中显示的C#代码使用ReadXmlSchema方法把图1中的大纲载入一个叫作orderDS的数据集 中。ReadXmlSchema建立了三个数据表,它们分别与大纲中定义的Customer、Order和LineItem 元素对应。因此你可以验证这个大纲在关系数据缓存中建立了预期的表,printDSShape方法把 每个表的名称写到控制台上,后面跟着列的列表和每列的数据类型。
列表1: 建立关系数据缓存的C#代码
以下是引用片段: using System;using System.Collections;using System.Data;using System.Data.SqlClient;using System.Xml; public class XMLMap{public static void Main(){// 建立数据集和读取大纲DataSet orderDS = new DataSet (“CustOrder”);orderDS.ReadXmlSchema(“CustOrderLitem.xsd”); // 打印数据集的形式printDSShape(orderDS); // 把一个XML格式的订单读入数据集 orderDS.ReadXml (“Order.xml”,System.Data.XmlReadMode.IgnoreSchema); // 打印数据集中的数据printDSData(orderDS); // 此处插入业务规则和数据库更新逻辑} private static void printDSShape(DataSet ds){foreach (DataTable dt in ds.Tables){Console.WriteLine(“{0}”,dt.TableName); // 打印列的名称和类型foreach (DataColumn dc in dt.Columns) Console.WriteLine(“t{0}t{1}”,dc.ColumnName,dc.DataType.ToString());} } private static void printDSData(DataSet ds){foreach (DataTable dt in ds.Tables){Console.WriteLine(“n{0}:”, dt.TableName); // 打印列的头foreach (DataColumn dc in dt.Columns)Console.Write(“{0} t”,dc.ColumnName);Console.WriteLine(“”); // 输出数据foreach (DataRow dr in dt.Rows){foreach(DataColumn dc in dt.Columns)System.Console.Write(“{0}t”,dr[dc]);System.Console.WriteLine (“”);}}}} |
仔细查看一下列的名称。尽管大纲中没有指定Customer_Id和Order_Id列,但是它们还是出 现在数据表中。ReadXmlSchema给数据集自动添加这些列。数据集把这些列用作外部键 (foreign key),以模拟Customer元素与它的Order元素之间、Order元素与它的LineItem元素 之间的关系。因为典型情况下XML使用嵌套的关系代替了外部键,所以数据集自动生成自己的主 键、数据表之间的外部键,并把它们存储在这些列中。
请同时仔细查看图3中的数据类型–数据集已经把来自XML大纲数据类型的数据类型映射为对 应的.NET数据类型。当你把XML文档载入数据集的时候,该数据集把来自XML的每一个值转换为 对应的.NET类型。
图3:生成的数据类型和记录
以下是引用片段: CustomerCustomerID System.StringCustomer_Id System.Int32 OrderOrderID System.Int64Order_Id System.Int32Customer_Id System.Int32 LineItemProductID System.Int32Quantity System.Int32UnitPrice System.DecimalOrder_Id System.Int32 Customer:CustomerID Customer_IdALFKI 0 Order:OrderID Order_Id Customer_Id10966 0 0 LineItem:ProductID Quantity UnitPrice Order_Id37 8 26.5 056 12 38 0 |
把大纲载入数据集之后,为了完成关系映射,你需要做的所有事情就是把XML数据载入该数 据集。列表1的ReadXml方法打开叫作Order.xml的文件,该文件如图2所示。接着,它把文件中 的数据读取到你刚才读取大纲建立的数据集中的数据表里。你的XML订单现在可以通过数据集访 问了。
为了演示如何访问数据集中的数据,列表1的printDSData方法在数据表中导航,对于每张表 ,都显示列的名称,紧接着显示这张表的所有的行。图3显示为ReadXmlSchema方法给数据集添 加的Customer_Id和Order_Id列自动生成了值。
请注意,Order.xml出现的三个元素–PO、Address和Description–没有映射到数据表中。 这些数据被忽略了,因为你提供给数据集的大纲没有包含这些元素,当数据集建立关系数据缓 存的外形并载入XML数据的时候,它简单地忽略了没有在大纲中描述的数据。即使在你从客户那 儿接收到的XML订单中包含了没有预料到的额外数据,这种简便特性也可以让你的代码正常地工 作。
建立使用数据缓存的应用程序
现在你已经知道如何使用数据集为XML数据建立关系数据缓存了,你可以应用这种技术来实 现一个执行业务逻辑并更新SQL Server的应用程序。当你使用数据集编程模型的时候实现业务 逻辑相对直接。ADO.NET为你提供了更新SQL Server中数据的几种选择,包括使用数据适配器、 编写自己的查询,以及执行存储过程。数据集使把XML数据映射成关系模型很容易,剩余的事情 是你的了。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
作者
相关推荐
-
.NET架构师:函数式语言做领域驱动设计
Scott一位.NET架构师,同时也是掌握函数式编程的作者,他很欣赏函数式编程,对于Scott来说,面向对象编程的那些概念也很恐怖,比如多态、泛型、继承、协变等。
-
软件开发就像炒股 关键看你怎么选股票!
本文作者Paulo Ortins在这里分享了对于选择哪种编程语言作为软件开发工作的起点的话题,并阐述了自己的观点。
-
增进离岸Java开发效率的十个提示
近日,Cygnet Infotech公司发布了一篇博文,谈到了如何增进离岸Java开发的效率。众多的ISV与软件厂商总是在不断寻找能以最低的代价实现其业务目标的解决方案。
-
Visual Studio 2013增强调试功能
Visual Studio 2013包含了若干诊断特性,能够帮助开发人员有效地调试他们的应用程序。