Шаблоны (templates) объединяют в себе квантово-волновой (SQL / XML) дуализм SQL Server. Козьма Прутков
мог бы смело их уподобить хранимым процедурам, которые допускают как SQL-, так и XPath-запросы. Шаблон
- это XML-файл, структура которого показана на рис.6.
<?xml version="1.0" encoding="utf-8" ?>
<Солянка xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<sql:header>
<sql:param name="Колво"></sql:param>
<sql:param name="Сумма">1000</sql:param>
</sql:header>
<sql:query client-side-xml="0">
SELECT TOP 1 * FROM Employees FOR XML AUTO
</sql:query>
<sql:query client-side-xml="1">
SELECT c.ContactName, COUNT(o.OrderDate) AS 'Кол-во'
FROM Customers c INNER JOIN Orders o ON c.CustomerID = o.CustomerID
GROUP BY c.ContactName HAVING COUNT(o.OrderDate) >= @Колво
FOR XML NESTED
</sql:query>
<sql:xpath-query mapping-schema="..\Schemas\SQLSchema1.xsd">
Клиент[number(Заказы/Заказ/Стоимость)>$Сумма]
</sql:xpath-query>
<sql:xpath-query mapping-schema="..\Schemas\SQLSchema2.xsd">
Сотрудник
</sql:xpath-query>
</Солянка>
Рис.6
Он состоит из частей трех основных типов. Каждая часть является опциональной. В
<sql:query> перечисляются
операторы SQL, в <sql:xpath-query> -
запросы XPath, в <sql:header>
описываются параметры для запросов
(как SQL, так и XPath). Привязка описаний параметров в заголовке к параметрам в запросах осуществляется
при помощи атрибута name ("Колво" - @Колво, "Сумма" - $Сумма). В одной секции <sql:query> может находиться
несколько SQL-запросов, в отличие от XPath-запросов, каждый из которых должен заключаться в свою секцию
<sql:xpath-query>. В данном примере SQL-запросы
пришлось разнести по разным секциям, так как первый из
них выполняется на сервере, а второй - на клиенте. Атрибут client-side-xml эквивалентен свойству ClientSideXml
класса SqlXmlCommand, с которым мы сталкивались в п.6. В <sql:query> могут присутствовать не только select'ы,
но и операторы объявления и модификации данных, а также вызовы хранимых процедур, что позволяет помещать
в секцию не просто несколько разрозненных операторов, а последовательность, связанную логикой выполнения.
Условие - весь select-вывод должен идти в виде XML. Допускаются опции AUTO и EXPLICIT. XPath-запросы
выполняются относительно заданной в атрибуте mapping-schema аннотированной схемы. Для каждого XPath-запроса
она может быть своя. Отметим, что некоторые (хоть все) из задействованных аннотированных схем могут
располагаться непосредственно в файле шаблона, так что предыдущий шаблон можно записать как:
<?xml version="1.0" encoding="utf-8" ?>
<Солянка xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<xs:chema xmlns:xs="http://www.w3.org/2001/XMLSchema"
_ xmlns:ms="urn:schemas-microsoft-com:mapping-schema"
id="SQLSchema2" sql:is-mapping-schema="1">
...Схема с рис.5...
</xs:schema>
...<sql:header> и <sql:query>-секции с рис.6...
<sql:xpath-query mapping-schema="..\Schemas\SQLSchema1.xsd">
Клиент[number(Заказы/Заказ/Стоимость)>$Сумма]
</sql:xpath-query>
<sql:xpath-query mapping-schema="#SQLSchema2">
Сотрудник
</sql:xpath-query>
</Солянка>
Рис.7
Таким образом, результат выполнения шаблона может состоять из фрагментов различных схем,
соответствующих разным секциям, объединенных корневым элементом. Остается сохранить его в файле
формата UTF-8 (Скрипт 11).
static void Execute_TemplateFile_SQLXML()
{
...
cmd.CommandText = "..\\Templates\\XMLTemplate1.xml";
cmd.CommandType = SqlXmlCommandType.TemplateFile;
SqlXmlParameter prm = cmd.CreateParameter();
prm.Name = "@Колво"; prm.Value = 20;
XmlDocument xml = new XmlDocument();
xml.Load(cmd.ExecuteStream());
...
}
Скрипт 11
Вызывающее приложение передает шаблону только один параметр @Колво = 20 (показать клиентов и
количество сделанных ими заказов, если оно превышает 20). Для другого запроса будет взято значение
параметра по умолчанию из шаблона - <sql:param
name="Сумма">1000</sql:param> (показать только тех клиентов,
которые сделали хотя бы один заказ на сумму свыше 1000). Если приложение не обеспечивает параметра при
вызове шаблона и секция <sql:header> не
содержит значение параметра по умолчанию, то для него будет
использовано значение по умолчанию, определенное в схеме SQL Server (DEFAULT для поля таблицы или для
параметра хранимой процедуры). Если значение по умолчанию в схеме SQL Server также не определено,
значение параметра полагается в NULL. Стоит обратить внимание на конвертацию number(Заказы/Заказ/Стоимость)
в одном из XPath-запросов в шаблонах рис.6, 7. Дело в том, что несмотря на объявление стоимости как
xs:type="xs:float"
параметр $Сумма норовит передаваться как nvarchar, что приводит к неверным результатам (напр. '5.00' > '1000').
Еще один, эквивалентный, способ вызова шаблона из SqlXml состоит в использовании свойства CommandStream
вместо CommandText. Соответственно должно быть скорректировано свойство CommandType.
...
cmd.CommandStream = new FileStream("..\\Templates\\XMLTemplate1.xml", FileMode.Open, FileAccess.Read);
cmd.CommandType = SqlXmlCommandType.Template;
...
Или даже так:
...
cmd.CommandStream = new MemoryStream();
StreamWriter sw = new StreamWriter(cmd.CommandStream, System.Text.Encoding.UTF8);
sw.Write("<?xml version='1.0' encoding='utf-8' ?> " +
"<Солянка xmlns:sql='urn:schemas-microsoft-com:xml-sql'>" +
...Содержание шаблона с рис.6...
"</Солянка>");
sw.Flush(); cmd.CommandStream.Position = 0;
cmd.CommandType = SqlXmlCommandType.Template;
...
В свойстве XslPath класса SqlXmlCommand может задаваться ссылка на XSL-преобразование, которому
подвергается сформированный на основе шаблона XML-файл. Преобразование можно также оговорить в
корневом элементе шаблона (например, sql:xsl="....xsl">).
Для повышения производительности применяется кэширование шаблонов, что означает, что они не выгружаются
из памяти после первого выполнения. Емкость кэша (в штуках) задается в
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SQLXML3\TemplateCacheSize и по умолчанию равна 31.
Чтобы запретить кэширование, необходимо зайти в закладку Advanced свойств виртуальной директории SQL
Server (см. п.13) и отметить Disable Caching of template. Аналогично настраивается кэширование аннотированных
схем (HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SQLXML3\SchemaCacheSize).
|
|