处理 xml 数据类型和 CLR 用户定义类型
后续版本的 Microsoft SQL Server 将删除该功能。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。
自 SQL Server 2005 起,在本机 XML Web 服务中,传递某些类型(如 xml 数据类型或公共语言运行时 (CLR) 用户定义类型)需要执行一些其他开发任务。本主题介绍为了使基于 XML Web 服务的应用程序能够在 Web 方法和参数化查询中使用 xml 和 CLR 用户定义类型而必须执行的任务。
注意 |
---|
本主题假定您已具有在 SQL Server 中部署本机 XML Web 服务的基础知识,包括熟悉某些任务,例如创建端点、借助 Web 方法来利用 SQL 可编程性,以及编写适用于使用其他内置 SQL 类型的 SQL Server 的基本 Web 客户端应用程序。如果要查看此信息,请参阅 本机 XML Web 服务概念、部署本机 XML Web 服务和使用本机 XML Web 服务的最佳方法。 |
在 Web 客户端应用程序中处理 xml 数据类型
要使 Web 客户端应用程序正确处理 xml 数据类型,其详细过程取决于应用下列哪一个方案:
使用作为端点的 Web 方法显示的存储过程。
使用端点的 SQL 批处理 (sqlbatch) 功能来执行参数化查询。
这两个方案都需要使用和填充 myEndpoint**::xml** 结构来处理 xml 数据类型的参数化实例。在此结构中,myEndpoint 表示在通过客户端代码传递 xml 数据类型的实例时所使用端点的真实名称。此结构在端点 Web 代理类中声明。
在添加或更新对 Visual Studio 项目中显示 Web 方法的端点的 Web 引用时,将创建 myEndpoint**::xml** 结构。但是,您必须基于在客户端应用程序代码中使用的是类型化的 XML 还是非类型化的 XML,相应地在自定义 Web 代理类中填充初始生成的 myEndpoint**::xml** 结构。
对于 Web 方法中的非类型化 xml 数据类型参数实例,myEndpoint**::xml** 结构在代理类中将它们显示为 System.Xml.XmlNode 类型的一个数组。因此,若要传入 xml 数据类型参数实例,请手动构造并填充 XML 节点的数组,或者最好使用 System.Xml.XmlDocumentFragment 来进行操作。有关详细信息,请参阅在 Visual Studio 客户端应用程序中使用 xml 数据类型。
对于 Web 方法中的类型化 xml,将在 Web 代理类中生成自定义类型并根据下列格式命名:方法名称加上单词 Type,后接参数名称。例如,如果通过名称 GetXmlInfo 来显示 Web 方法,并且采用名称为 T 的 xml 数据类型参数来传递作为输入的类型化的 XML,则在 Web 代理类中显示的自定义类型的名称将是 GetXmlInfoTypeT。因为此自定义类型是从 myEndpoint**::xml** 结构继承的,因此它类似于将类型化的 XML 作为一个 System.Xml.XmlNode 数组显示。
在参数化查询中处理 xml 数据类型与在 Web 方法中处理 xml 数据类型相似,但有一点不同:必须通过非类型化的 XML 使用的类型 (myEndpoint**::xml**) 从客户端传递类型化的 XML。
准备好 myEndpoint**::xml** 结构后,便可以将 xml 数据类型实例作为已定义结构中的一个 System.Xml.XmlNode 数组来显示,而该结构又可以包含在 SqlParameter.Value 对象中。
参数化查询要求具有 SQL 批处理功能。这可能涉及下面的其他准备工作:
端点必须启用 SQL。这意味着创建或修改端点时,使用了 BATCHES=ENABLED。
在 Web 代理类中,为启用批处理的端点添加或更新 Web 引用时,将包含 sqlbatch() 方法。
对于类型化的 XML 参数,将更新 Web 代理类中的 sqlbatch() 方法,以包含与注册 System.Data.SqlClient.SqlParameter 对象的 XML 架构集合有关的任何其他属性(XmlSchemaCollectionDatabase、XmlSchemaCollectionName、XmlSchemaCollectionOwningSchema)的设置。
注意 |
---|
对于显示 xml 数据类型的 Web 方法和参数化查询,在输出中将返回 System.Data.DataSet(作为对象数组的一部分)并将其内容放置在 DataGrid 中以在客户端应用程序中将结果可视化,DataSet 不使用 Web 代理类型 (myEndpoint::xml),而使用 CLR System.Data.SqlTypes.SqlXml 类型。 |
在 Web 客户端应用程序中处理 CLR 用户定义类型
若要在 Web 客户端应用程序中处理 CLR 用户定义类型,必须完成下列步骤:
编写 CLR 用户定义类型,并在 DLL(如 MyType.dll)中对其进行编译。
在 Visual Studio 2005 中,编写 CLR 用户定义类型(类或结构)并将其编译为一个程序集。该类型程序集必须符合 SQL Server 对实现用户定义类型方面的要求,从而能够在 SQL Server 实例上安装和注册程序集。有关详细信息,请参阅 CLR 用户定义类型中的“UDT 实现方面的要求”。
若要生成 XML 序列化程序附带 DLL,如果您尚未实现 IXMLSerializable,则可以对类型程序集 DLL 运行 Sgen.exe。生成的 DLL 将具有与 MyType.XmlSerializers.dll 类似的名称。
除了满足 SQL Server 对 CLR 用户定义类型方面的基本要求外,CLR 用户定义类型还必须是 XML 可序列化的,才能在 SQL Server 中使用本机 XML Web 服务。有关详细信息,请参阅 CLR 用户定义类型中的“XML 序列化”。
使用 CREATE ASSEMBLY 在 SQL Server 实例上安装类型程序集 DLL。
如果尚未实现 IXMLSerializable 但完成了步骤 2,则仍必须使用 CREATE ASSEMBLY 在 SQL Server 实例上安装 XML 序列化程序附带 DLL。
将 CLR 用户定义类型序列化为 XML 并将其包含在上一部分介绍的 myEndpoint**::xml** 类似结构中。
在服务器上安装 CLR 用户定义类型后,若要从本机 XML Web 服务客户端应用程序将此 CLR 用户定义类型的实例传递到 SQL Server,首先必须将 CLR 用户定义类型序列化为 XML 格式并将其包含在 XML结构中。
下列代码显示了如何将 CLR 用户定义类型序列化为 XML 格式并将其放入 XML 元素 (System.Xml.XmlElement)。
// Create the user-defined type class on the client. SqlString s = new SqlString("0:0"); UdtClientApp.Point pnt = Point.Parse(s); // Invoke the method and pass in a user-defined type.You will need // to convert this to XmlElement before you can pass it to SQL Server. System.IO.MemoryStream writer = new System.IO.MemoryStream(); System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(UdtClientApp.Point)); serializer.Serialize(writer, pnt); writer.Seek(0, System.IO.SeekOrigin.Begin); System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument(); xmlDoc.Load(writer); System.Xml.XmlElement udtXml = xmlDoc.DocumentElement;
根据 CLR 用户定义类型是否出现在客户端,您可能还必须将输出参数从其 CLR 用户定义类型 XML 格式反序列化回其用户定义类型格式。
下列代码显示了如何在客户端代码中将用户定义类型 XML 反序列化回 CLR 用户定义类型。在此示例中,CLR 用户定义类型为 Point。
Object[] results = proxy.GetPointUdt(Convert.ToInt16(textBox1.Text), ref udtXml); //Deserialze the XML into user-defined type. TextReader reader = new StringReader(udtXml.OuterXml); // pnt was already defined as UdtClientApp.Point pnt = Point.Parse(s); pnt = (UdtClientApp.Point) serializer.Deserialize(reader);
请注意,如果在客户端将 CLR 用户定义类型作为非类型化的 XML 使用,则将不必执行此反序列化过程。
也可以将 CLR 用户定义类型作为参数按照与 xml 数据类型类似的方法传递到参数化查询。必须使用 myEndpoint**::xml** 类型从客户端传递 XML 序列化格式的 CLR 用户定义类型。
对于涉及 CLR 用户定义类型的参数化查询,将在 System.Data.SqlClient.SqlParameter 结构上设置不同的值。例如,下列属性设置用于 CLR 用户定义类型:
必须将 SqlDbType 属性设置为一个 Udt 值。
对于 ClrTypeName 属性,必须按照所安装的用户定义类型在 SQL Server 实例上的注册,将其设置为该用户定义类型的 SQL Server 三部分限定名 (MyDatabase**.MySchema.**MyUdtType)。