Класс XmlCommand
Класс XmlCommand выполняет XML-запрос и используется как
свойство классов XsltProcessor и
XQueryProcessor. Вы обеспечиваете класс
XmlCommand источниками данных и параметрами, необходимыми для
выполнения запроса. Класс предоставляет единственный метод
Execute(), описанный далее в Таблице 2, который может
использоваться для выполнения множественных запросов к источнику данных любого
типа.
Метод |
Описание |
Execute(context-document-uri, datasources, results) |
Исполняет откомпилированный XQuery-запрос к одному или более
источникам данных (параметр datasources), которые представлены экземпляром
класса XmlResolver, и выводит результаты в экземпляр класса TextWriter
(параметр results). Метод вызывается после того, как метод Compile()
завершил свою работу. Если запрос использует контекст документа (т.е., “/”
или функцию input()языка XQuery), необходимо передавать контекст документа
через параметр context-document-uri. |
Таблица 2. Описание метода Execute() класса XmlCommand
Прежде чем приступить к рассмотрению примеров, иллюстрирующих применение
класса XqueryProcessor обратимся к краткой характеристике
функций и операторов языка XQuery поддерживаемых .NET Framework 1.2.
Как следует из документации к NET Framework SDK 1.2 простой XQuery-запрос
обычно состоит из ссылки на документ (чаще всего представляющую собой путь к
документу). Спецификация XQuery предлагает несколько способов ввода данных XML с
использованием следующих функций: document(),
input(), collection(), а также дополнительной
функции map:view(), которая используется при обращении к XML-представлению
реляционных баз данных SQL Сервера.
Функция document() возвращает документ(ы), к которому
производится запрос и связана с объектом XmlUrlResolver который
определяет название документа вместе с путем к файлу или путем URL.
declare namespace PD='http://www.adventure-works.com/schemas/products/description'
<Root>
{document('http://server/.../XMLDoc.xml')/PD:ProductDescription/
PD:Summary }
</Root>
или
<Root>
{document(c:\MyFolder\...\XMLDoc.xml')/PD:ProductDescription/
PD:Summary}
</Root>
При использовании класса XmlDataSourceResolver можно
определить символический псевдоним документа как показано ниже:
declare namespace PD='http://www.adventure-works.com/schemas/products/description'
<Root>
{document('XMLDoc')/PD:ProductDescription/PD:Summary}
</Root>
Функция input() возвращает входную последовательность.
Например:
declare namespace PD='http://www.adventure-works.com/schemas/products/description'
<Root>
{input()/PD:ProductDescription/PD:Summary }
</Root>
Обратите внимание, что функция input() в запросе не
идентифицирует документ к которому производится запрос, вместо этого в запросе
использован контекст документа. Контекст документа должен быть определен в
Execute() функции.
Можно также создавать многократные запросы к документам как показано
ниже:
declare namespace PD='http://www.adventure-works.com/schemas/products/description'
<Root>
<Query1>
{ document('XmlDoc')/PD:ProductDescription/PD:Features }
</Query1>
<Query2>
{input()/PD:ProductDescription/PD:Summary }
</Query2>
</Root>
В архитектуре XML-запроса документ, к которому производится запрос, может
представлять собой XML-документ или XML-представление реляционных данных SQL
Сервера. При использовании XML-представления необходимо создать объект
SqlConnection и определить строку подключения к источнику
данных. После этого добавить это подключение к объекту
XmlDataSourceResolver перед выполнением запроса.
XQuery функции и операторы для Whidbey “Alpha” определены в рабочем проекте
по адресу: http://www.w3.org/TR/2002/WD-XQuery-operators-20021115/
(http://www.w3.org/TR/2002/WD-XQuery-operators-20021115/ ) .
XQuery функции содержат “fn:” префикс, который указывает на
пространство имен ‘http://www.w3.org/TR/2002/WD-XQuery-operators-20021115/’ и
автоматически связывает их с XQuery процессором. Это позволяет использовать
любые функции XQuery непосредственно в XQuery выражениях без предварительного
объявления их в XQuery-прологе как показано ниже:
declare namespace PD='http://www.adventure-works.com/schemas/products/description'
<Root>
{fn:upper-case(document('XMLDoc')/PD:ProductDescription
/PD:Summary)}
</Root>
Операторы XQuery используемые в XQuery-выражениях подразделяются в
зависимости от типа операндов на:
- Операторы простой арифметики над числовыми данными;
- Логические операторы;
- Операторы для выполнения операций над последовательностями.
Для операторов XQuery также оперделен префикс “op:”, но на
практике проще использовать неявный синтаксис операторов. По этой причине,
поддержка для явного синтаксиса (op:func()) не была реализована
в Whidbey “Alpha”.
Следующий пример иллюстрирует использование оператора XQuery “+”, чтобы
увеличить значение элемента на единицу.
declare namespace PD='http://www.adventure-works.com/schemas/products/description'
<Root>
{ let $ProdID := fn:data(document('XMLDoc')/PD:ProductDescription/
@ProductModelID)
return cast as xs:integer($ProdID) + 1
}
</Root>
Рассмотрим на примерах использование класса
XQueryProcessor.
Пример представленный ниже использует Xml-документ, находящийся в файле
books.xml (представленный в Приложении к статье) для запроса
книг по критерию используя XQueryProcessor класс.
using System;
using System.IO;
using System.Xml;
using System.Xml.Query;
using System.Data.SqlXml;
namespace SamplesXQuery
{
class XQueryExample1
{
[STAThread]
static void Main (string[] args)
{
XQueryXMLDocument();
}
public static void XQueryXMLDocument()
{
//Файл с результатами
StreamWriter writer = new StreamWriter("output.xml");
try
{
//Инициализация XmlDataSourceResolver
XmlDataSourceResolver datasource=new XmlDataSourceResolver();
datasource.Add("bookstore", "books.xml");
//Запрос
string query = "<bookstore> { for $b in document('bookstore')/bookstore/book where $b/@genre='philosophy' and $b/@publicationdate='1991'
return $b/title } </bookstore>";
// Инициализация XQueryProcessor
XQueryProcessor xq = new XQueryProcessor();
//Компиляция и выполнение запроса
xq.Compile(query);
xq.Execute(datasource, writer);
}
catch (Exception e)
{
Console.WriteLine ("Exception: " + e.ToString ());
}
finally
{
writer.Close();
}
}
}
}
Сначала создается объект XmlDataSourceResolver для связи с
источником данных (файл books.xml). Это позволяет в функции
document(), являющейся частью XQuery-запроса ссылаться на этот
источник через псевдоним bookstore. Далее формируется запрос,
представленный значением строковой переменной, который выбирает записи, у
которых значения атрибутов genre и
publicationdate равны соответственно
philosophy и 1991. После этого запрос
компилируется и выполняется с использованием методов Compile()
и Execute() класса XQueryProcessor. Результат
выводится в файл output.xml.
Класс XPathDocument2 предназначен для эффективной работы с
XQuery. В следующем примере создается запрос к двум Xml-документам. Этот пример
идентичен предыдущему, за исключением того, что документ
books2.xml загружен через XPathDocument2 и
затем добавлен к XmlDataSourceResolver. Такой способ может быть
полезен, когда вы хотите редактировать документ с использованием
XPathEditor перед выполнением XQuery-запроса.
using System;
using System.IO;
using System.Xml;
using System.Xml.Query;
using System.Data.SqlXml;
namespace SamplesXQuery
{
class XQueryExample2
{
[STAThread]
static void Main (string[] args)
{
XQueryXMLDocument();
}
public static void XQueryXMLDocument()
{
StreamWriter writer =new StreamWriter("output.xml");
try
{
// Инициализация XmlDataSourceResolver
XmlDataSourceResolver datasource =new XmlDataSourceResolver();
datasource.Add("bookstore", "books.xml");
XPathDocument2 doc =new XPathDocument2(datasource.NameTable);
doc.Load("books2.xml");
datasource.Add("bookstore2", doc.CreateXPathNavigator2());
// Запрос
string query = "<bookstore> { for $b in document('bookstore')
/bookstore/book where $b/@genre='philosophy'
and $b/@publicationdate='1991' return $b/title }
{ for $b2 in document('bookstore2')/bookstore/book where
$b2/@genre='autobiography' and $b2/@publicationdate='1981'
return $b2/title } </bookstore>";
// Инициализация XQueryProcessor
XQueryProcessor xq =new XQueryProcessor();
// Компилировать и выполнить запрос
xq.Compile(query);
xq.Execute(datasource, writer);
}
catch (Exception e)
{
Console.WriteLine ("Exception: " + e.ToString ());
}
finally
{
writer.Close();
}
}
}
}
XQuery-запрос, используемый в этом примере, находит все книги со значением
атрибута genre равным philosophy и значением
атрибута publicationdate равным 1991 из файла
bookstore.xml и все книги со значением атрибута
genre равным autobiography и значением
атрибута publicationdate равным 1981 из файла
bookstore2.xml.
Следующий пример использует функцию map:view(), чтобы
сделать запрос к данным SQL Сервера через XML-представление. Источник данных
добавляется к XmlDataSourceResolver через класс
SqlConnection. XML-представление файла данных через псевдоним
nwind добавляется к XmlViewSchemaDictionary и
затем используется в функции map:view() чтобы выполнить
XQuery-запрос.
XmlViewSchemaDictionary представляет собой набор объектов
XmlViewSchema с помощью которых метод Add()
добавляет XML-представления используемые для запросов и модификации данных SQL
Сервера. Вы можете передавать ссылки на файл MSD (.msd) методу
Add(), который автоматически создает новый объект
XmlViewSchema, компилирует XML-представление и добавляет
результат к XmlViewSchemaDictionary. Таким образом, класс
XmlViewSchema представляет собой откомпилированное
XML-представление.
using System;
using System.IO;
using System.Xml;
using System.Xml.Query;
using System.Data.SqlXml;
using System.Data.SqlClient;
namespace SamplesXQuery
{
class XQueryExample3
{
[STAThread]
static void Main (string[] args)
{
XQuerySqlData();
}
public static void XQuerySqlData()
{
//Создать соединение с данными SQL сервера
SqlConnection myConn =new SqlConnection("server="My Server";
database=northwind;Integrated Security=SSPI");
StreamWriter writer =new StreamWriter("output.xml");
try
{
myConn.Open();
//Инициализация XQueryProcessor
XQueryProcessor xq =new XQueryProcessor();
//Добавление XML-представления к XmlViewSchemaDictionary
xq.XmlViewSchemaDictionary.Add("nwind", new
XmlTextReader("northwind.msd"));
//Добавление источника данных к XmlDataSourceResolver
XmlDataSourceResolver datasource =new XmlDataSourceResolver();
datasource.Add("Northwind", myConn);
//Запрос
string query = "declare namespace
map='http://schemas.microsoft.com/xml/2002/09/28/
mappingfunctions'<Root>{map:view('nwind')/Customers}</Root>";
xq.Compile(query);
xq.Execute(datasource, writer);
}
catch (Exception e)
{
Console.WriteLine ("Exception: " + e.ToString ());
}
finally
{
writer.Close();
myConn.Close();
}
}
}
}
XQuery-запрос представленный в примере возвращает всех заказчиков
(Customers) из базы данных Northwind используя
ее Xml-представление.
Xml-схема для Xml-представления Northwind:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Customers">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Order">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Product">
<xsd:complexType>
<xsd:attribute name="UnitQuantity" type="xsd:integer"/>
<xsd:attribute name="ProductName" type="xsd:string"/>
<xsd:attribute name="UnitPrice" type="xsd:string" />
<xsd:attribute name="QuantityPerUnit" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="CustomerID" type="xsd:string" />
<xsd:attribute name="orderid" type="xsd:string"/>
<xsd:attribute name="OrderDate" type="xsd:string"/>
<xsd:attribute name="ShipCity" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="CustomerID" type="xsd:string" />
<xsd:attribute name="Country" type="xsd:string" />
<xsd:attribute name="City" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Файл msd-схемы для Xml-представления Northwind:
<m:MappingSchema
xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">
<m:DataSources>
<m:DataSource Name="XML" Direction="Target" Type="Xml">
<m:Schema Location="northwind.xsd" />
</m:DataSource>
<m:DataSource Name="Northwind" Direction="Source" Type="SQL Server">
<m:Schema Location="northwind.rsd" />
<m:Variable Name="Orders" Select="Orders" />
<m:Variable Name="Customers" Select="Customers"/>
<m:Variable Name="Products" Select="Products"/>
<m:Variable Name="OrderDetails" Select="Order Details"/>
<m:Relationship Name="rel1" FromVariable="Customers"
ToVariable="Orders">
<m:FieldJoin From="CustomerID" To="CustomerID" />
</m:Relationship>
<m:Relationship Name="rel2" FromVariable="Orders"
ToVariable="OrderDetails">
<m:FieldJoin From="OrderID" To="OrderID" />
</m:Relationship>
<m:Relationship Name="rel3" FromVariable="OrderDetails"
ToVariable="Products">
<m:FieldJoin From="ProductID" To="ProductID" />
</m:Relationship>
</m:DataSource>
</m:DataSources>
<m:Mappings>
<m:Map SourceVariable="Customers"
TargetSelect="/Customers/Customer">
<m:FieldMap SourceField="CompanyName" TargetField="@name" />
<m:FieldMap SourceField="CustomerID" TargetField="@CustomerID" />
<m:FieldMap SourceField="Country" TargetField="@Country" />
<m:FieldMap SourceField="City" TargetField="@City" />
</m:Map>
<m:Map SourceVariable="Orders"
TargetSelect="/Customers/Customer/Order">
<m:FieldMap SourceField="orderid" TargetField="@orderid" />
<m:FieldMap SourceField="CustomerID" TargetField="@CustomerID" />
<m:FieldMap SourceField="OrderDate" TargetField="@OrderDate" />
<m:FieldMap SourceField="ShipCity" TargetField="@ShipCity" />
</m:Map>
</m:Mappings>
</m:MappingSchema>
Файл rsd-схемы для Xml-представления Northwind:
<rsd:Database Owner="sa" Name="Northwind"
xmlns:rsd="http://schemas.microsoft.com/data/2002/09/28/rsd">
<rsd:Schema Name="dbo">
<rsd:Tables>
<rsd:Table Name="Orders">
<rsd:Columns>
<rsd:Column Name="OrderID" AutoIncrement="1" IncrementStep="1"
SqlType="int" IncrementSeed="1" />
<rsd:Column Name="CustomerID" SqlType="nchar" AllowDbNull="1"
Length="5" />
<rsd:Column Name="EmployeeID" SqlType="int" AllowDbNull="1" />
<rsd:Column Name="OrderDate" SqlType="datetime" AllowDbNull="1" />
<rsd:Column Name="RequiredDate" SqlType="datetime"
AllowDbNull="1"/>
<rsd:Column Name="ShippedDate" SqlType="datetime"
AllowDbNull="1"/>
<rsd:Column Name="ShipVia" SqlType="int" AllowDbNull="1" />
<rsd:Column Name="Freight" SqlType="money" AllowDbNull="1" />
<rsd:Column Name="ShipName" SqlType="nvarchar" AllowDbNull="1"
Length="40" />
<rsd:Column Name="ShipAddress" SqlType="nvarchar" AllowDbNull="1"
Length="60" />
<rsd:Column Name="ShipCity" SqlType="nvarchar" AllowDbNull="1"
Length="15" />
<rsd:Column Name="ShipRegion" SqlType="nvarchar" AllowDbNull="1"
Length="15" />
<rsd:Column Name="ShipPostalCode" SqlType="nvarchar"
AllowDbNull="1" Length="10" />
<rsd:Column Name="ShipCountry" SqlType="nvarchar" AllowDbNull="1"
Length="15" />
</rsd:Columns>
<rsd:Constraints>
<rsd:PrimaryKey Name="PK_Orders">
<rsd:ColumnRef Name="OrderID" />
</rsd:PrimaryKey>
<rsd:ForeignKey Name="FK_Orders_Customers"
ForeignTable="Customers"
UpdateRule="None" DeleteRule="None">
<rsd:ColumnMatch Name="CustomerID" ForeignName="CustomerID" />
</rsd:ForeignKey>
</rsd:Constraints>
</rsd:Table>
<rsd:Table Name="Products">
<rsd:Columns>
<rsd:Column Name="ProductID" AutoIncrement="1" IncrementStep="1"
SqlType="int" IncrementSeed="1" />
<rsd:Column Name="ProductName" SqlType="nvarchar" Length="40" />
<rsd:Column Name="SupplierID" SqlType="int" AllowDbNull="1" />
<rsd:Column Name="CategoryID" SqlType="int" AllowDbNull="1" />
<rsd:Column Name="QuantityPerUnit" SqlType="nvarchar"
AllowDbNull="1" Length="20" />
<rsd:Column Name="UnitPrice" SqlType="money" AllowDbNull="1" />
<rsd:Column Name="UnitsInStock" SqlType="smallint"
AllowDbNull="1"/>
<rsd:Column Name="UnitsOnOrder" SqlType="smallint"
AllowDbNull="1"/>
<rsd:Column Name="ReorderLevel" SqlType="smallint"
AllowDbNull="1"/>
<rsd:Column Name="Discontinued" SqlType="bit" />
</rsd:Columns>
<rsd:Constraints>
<rsd:PrimaryKey Name="PK_Products">
<rsd:ColumnRef Name="ProductID" />
</rsd:PrimaryKey>
</rsd:Constraints>
</rsd:Table>
<rsd:Table Name="Order Details">
<rsd:Columns>
<rsd:Column Name="OrderID" SqlType="int" />
<rsd:Column Name="ProductID" SqlType="int" />
<rsd:Column Name="UnitPrice" SqlType="money" />
<rsd:Column Name="Quantity" SqlType="smallint" />
<rsd:Column Name="Discount" SqlType="real" />
</rsd:Columns>
<rsd:Constraints>
<rsd:PrimaryKey Name="PK_Order_Details">
<rsd:ColumnRef Name="OrderID" />
<rsd:ColumnRef Name="ProductID" />
</rsd:PrimaryKey>
<rsd:ForeignKey Name="FK_Order_Details_Orders"
ForeignTable="Orders" UpdateRule="None" DeleteRule="None">
<rsd:ColumnMatch Name="OrderID" ForeignName="OrderID" />
</rsd:ForeignKey>
<rsd:ForeignKey Name="FK_Order_Details_Products"
ForeignTable="Products" UpdateRule="None" DeleteRule="None">
<rsd:ColumnMatch Name="ProductID" ForeignName="ProductID" />
</rsd:ForeignKey>
</rsd:Constraints>
</rsd:Table>
<rsd:Table Name="Customers">
<rsd:Columns>
<rsd:Column Name="CustomerID" SqlType="nchar" Length="5" />
<rsd:Column Name="CompanyName" SqlType="nvarchar" Length="40" />
<rsd:Column Name="ContactName" SqlType="nvarchar" AllowDbNull="1"
Length="30" />
<rsd:Column Name="ContactTitle" SqlType="nvarchar"
AllowDbNull="1"
Length="30" />
<rsd:Column Name="Address" SqlType="nvarchar" AllowDbNull="1"
Length="60" />
<rsd:Column Name="City" SqlType="nvarchar" AllowDbNull="1"
Length="15" />
<rsd:Column Name="Region" SqlType="nvarchar" AllowDbNull="1"
Length="15" />
<rsd:Column Name="PostalCode" SqlType="nvarchar" AllowDbNull="1"
Length="10" />
<rsd:Column Name="Country" SqlType="nvarchar" AllowDbNull="1"
Length="15" />
<rsd:Column Name="Phone" SqlType="nvarchar" AllowDbNull="1"
Length="24" />
<rsd:Column Name="Fax" SqlType="nvarchar" AllowDbNull="1"
Length="24" />
</rsd:Columns>
<rsd:Constraints>
<rsd:PrimaryKey Name="PK_Customers">
<rsd:ColumnRef Name="CustomerID" />
</rsd:PrimaryKey>
</rsd:Constraints>
</rsd:Table>
</rsd:Tables>
</rsd:Schema>
</rsd:Database>
Следующий пример использует множественные Xml-представления используя функцию
map:view() для запроса данных SQL Сервера. Для каждого XML-
представления файл схемы (.msd) добавлен к
XmlViewSchemaDictionary и упомянут в функции
map:view() при выполнении XQuery-запроса. В этом примере
Xml-представление базы Northwind разбито на два отдельных
Xml-представления: одно для заказчиков (Customers) с именем
customersView и одно для заказов (Orders) с
именем ordersView. Далее приведены Xml-схемы и msd-схемы этих
Xml-представлений. RSD файл базы Northwind остается
неизменным.
Xml-схема для Xml-представления customersView:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Customer">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="CustomerID" type="xsd:string"/>
<xsd:attribute name="Country" type="xsd:string"/>
<xsd:attribute name="City" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Файл msd-схемы для Xml-представления customersView:
<m:MappingSchema
xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">
<m:DataSources>
<m:DataSource Name="XML" Direction="Target" Type="Xml">
<m:Schema Location="customers.xsd"/>
</m:DataSource>
<m:DataSource Name="Northwind" Direction="Source"
Type="SQL Server">
<m:Schema Location="northwind.rsd"/>
<m:Variable Name="Customers" Select="Customers"/>
</m:DataSource>
</m:DataSources>
<m:Mappings>
<m:Map SourceVariable="Customers" TargetSelect="/Customer">
<m:FieldMap SourceField="CompanyName" TargetField="@name"/>
<m:FieldMap SourceField="CustomerID"
TargetField="@CustomerID"/>
<m:FieldMap SourceField="Country" TargetField="@Country"/>
<m:FieldMap SourceField="City" TargetField="@City"/>
</m:Map>
</m:Mappings>
</m:MappingSchema>
Xml-схема для Xml-представления ordersView:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Order">
<xsd:complexType>
<xsd:attribute name="CustomerID" type="xsd:string"/>
<xsd:attribute name="orderid" type="xsd:string"/>
<xsd:attribute name="OrderDate" type="xsd:string"/>
<xsd:attribute name="ShipCity" type="xsd:string"/>
<xsd:attribute name="ShipDate" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Файл msd-схемы для Xml-представления ordersView:
<m:MappingSchema
xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">
<m:DataSources>
<m:DataSource Name="XML" Direction="Target" Type="Xml">
<m:Schema Location="orders.xsd"/>
</m:DataSource>
<m:DataSource Name="Northwind" Direction="Source"
Type="SQL Server">
<m:Schema Location="northwind.rsd"/>
<m:Variable Name="Orders" Select="Orders"/>
</m:DataSource>
</m:DataSources>
<m:Mappings>
<m:Map SourceVariable="Orders" TargetSelect="/Order">
<m:FieldMap SourceField="orderid" TargetField="@orderid"/>
<m:FieldMap SourceField="CustomerID"
TargetField="@CustomerID"/>
<m:FieldMap SourceField="OrderDate"
TargetField="@OrderDate"/>
<m:FieldMap SourceField="ShipCity" TargetField="@ShipCity"/>
<m:FieldMap SourceField="ShippedDate"
TargetField="@ShipDate"/>
</m:Map>
</m:Mappings>
</m:MappingSchema>
Код примера:
using System;
using System.IO;
using System.Xml;
using System.Xml.Query;
using System.Data.SqlXml;
using System.Data.SqlClient;
namespace SamplesXQery
{
class XQueryExample4
{
[STAThread]
static void Main (string[] args)
{
MultipleXQuerySqlData();
}
public static void MultipleXQuerySqlData()
{
//SQL-соединение
SqlConnection myConn =new SqlConnection("server="My Server";
database=northwind;Integrated Security=SSPI");
StreamWriter writer =new StreamWriter("output.xml");
try
{
myConn.Open();
//Инициализация XQueryProcessor
XQueryProcessor xq =new XQueryProcessor();
//Добавление XML-представлений
xq.XmlViewSchemaDictionary.Add("customersView", new
XmlTextReader("customers.msd"));
xq.XmlViewSchemaDictionary.Add("ordersView", new
XmlTextReader("orders.msd"));
//Добавление соединения с базой данных
XmlDataSourceResolver datasource =new
XmlDataSourceResolver();
datasource.Add("Northwind", myConn);
//Запрос
string query = "declare namespace
map='http://schemas.microsoft.com/xml/2002/09/28/
mappingfunctions'<root>{for $customer in
map:view('customersView')/Customer let $orders :=
map:view('ordersView')/Order[@CustomerID=
$customer/@CustomerID] return element Customer
{$customer/@*, $orders}} </root>";
xq.Compile(query);
xq.Execute(datasource, writer);
}
catch (Exception e)
{
Console.WriteLine ("Exception: " + e.ToString ());
}
finally
{
writer.Close();
myConn.Close();
}
}
}
}
XQuery-запрос, используемый в примере, возвращает всех заказчиков
(Customers) и соответствующие им заказы
(Orders).
Вы можете также создавать Xml-представления данных от нескольких подключений
и даже данных, которые физически могут быть расположены на разных машинах. В
следующем примере используется Xml-представление с именем
productsView. Это представление также является подмножеством
Xml-представления базы Northwind и отображает таблицу продуктов
(Product). Xml-схема и msd-файл для Xml-представления
productsView показаны ниже:
Xml-схема для Xml-представления productsView:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Product">
<xsd:complexType>
<xsd:attribute name="UnitQuantity" type="xsd:integer"/>
<xsd:attribute name="ProductName" type="xsd:string"/>
<xsd:attribute name="UnitPrice" type="xsd:decimal"/>
<xsd:attribute name="QuantityPerUnit" type="xsd:string"/>
<xsd:attribute name="ProductID" type="xsd:integer"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Файл msd-схемы для Xml-представления productsView:
<m:MappingSchema
xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">
<m:DataSources>
<m:DataSource Name="XML" Direction="Target" Type="Xml">
<m:Schema Location="products.xsd"/>
</m:DataSource>
<m:DataSource Name="Northwind" Direction="Source"
Type="SQL Server">
<m:Schema Location="northwind.rsd"/>
<m:Variable Name="Products" Select="Products"/>
</m:DataSource>
</m:DataSources>
<m:Mappings>
<m:Map SourceVariable="Products" TargetSelect="/Product">
<m:FieldMap SourceField="productname"
TargetField="@ProductName"/>
<m:FieldMap SourceField="UnitPrice" TargetField="@UnitPrice"/>
<m:FieldMap SourceField="QuantityPerUnit"
TargetField="@QuantityPerUnit"/>
<m:FieldMap SourceField="ProductID" TargetField="@ProductID"/>
</m:Map>
</m:Mappings>
</m:MappingSchema>
Код примера подобен предыдущему за исключением того, что к
XmlViewSchemaDictionary добавлено еще Xml-представление
productsView. Два источника данных от разных подключений
добавлены к XmlDatasourceResolver - источник данных
Northwind, показанный в предыдущем примере и новый с именем
productsDb.
using System;
using System.IO;
using System.Xml;
using System.Xml.Query;
using System.Data.SqlXml;
using System.Data.SqlClient;
namespace SamplesXQuery
{
class XQueryExample5
{
[STAThread]
static void Main (string[] args)
{
MultiXQueryManySqlData();
}
public static void MultiXQueryManySqlData()
{
//Множественное SQL-соединение
SqlConnection myConn =new SqlConnection("server="My server";
database=northwind;Integrated Security=SSPI");
SqlConnection productsConn =new SqlConnection("server="My
server";database=northwind; Integrated Security=SSPI");
StreamWriter writer =new StreamWriter("output.xml");
try
{
myConn.Open();
//Инициализация XQueryProcessor
XQueryProcessor xq =new XQueryProcessor();
//Добавление XML-представлений
xq.XmlViewSchemaDictionary.Add("customersView", new
XmlTextReader("customers.msd"));
xq.XmlViewSchemaDictionary.Add("ordersView", new
XmlTextReader("orders.msd"));
xq.XmlViewSchemaDictionary.Add("productsView", new
XmlTextReader("products.msd"));
//Добавление соединений с базами данных
XmlDataSourceResolver datasource =new
XmlDataSourceResolver();
datasource.Add("Northwind", myConn);
datasource.Add("productsDb", productsConn);
datasource.Add("orderDetails", "orderdetails.xml");
//Запрос
string query = "declare namespace
map='http://schemas.microsoft.com/xml/2002/09/28/
mappingfunctions'<root> {for $product in
map:view('productsView')/Product return element Product
{ $product/@*, for $orderdetails in
document('orderDetails')/details/orderdetail[@ProductID=
$product/@ProductID] for $orders in
map:view('ordersView')/Order[@orderid=$orderdetails/@OrderID]
let $customers :=map:view('customersView')/Customer
[@CustomerID=$orders/@CustomerID] return $customers}}
</root>";
xq.Compile(query);
xq.Execute(datasource, writer);
}
catch (Exception e)
{
Console.WriteLine ("Exception: " + e.ToString ());
}
finally
{
writer.Close();
myConn.Close();
}
}
}
}
XQuery-запрос, используемый в этом примере, возвращает все элементы таблицы
продуктов (Product). Дополнительно, в составе элементов
Product, значение атрибута ProductID которых
совпадает со значением атрибута ProductID элементов
orderDetails (файл orderdetails.xml) выводятся
заказчики (Customer), элементы заказов (Order)
которых имеют значение атрибута OrderID совпадающее со
значением одноименного атрибута элементов
orderDetails.