Тип команды | Значение в ADO |
Запрос Transact-SQL | {C8B522D7-5CF3-11CE-ADE5-00AA0044773D} |
Запрос XPath | {EC2A4293-E898-11D2-B1B7-00C04F680C56} |
Запрос в XML-шаблоне | {5D531CB2-E6Ed-11D2-B252-00C04F681B71} |
Поведение провайдера по умолчанию | {C8B521FB-5CF3-11CE-ADE5-00AA0044773D} |
Так как результат выполнения объекта Command теперь не всегда может иметь реляционный характер, его нельзя помещать в объект Recordset. Название нового стандартного свойства Output Stream говорит само за себя: результат выполнения объекта Command может быть сохранен в потоке (любом объекте, поддерживающим интерфейс IStream). Кроме этого, поскольку запрос (свойство CommandText) теперь может представлять собой запрос XPath, нужно как-то задать аннотированную схему для него. Это делается с помощью стандартного свойства Mapping Schema. Пора переходить к примерам.
Использование Command для формирования XML-документа на сервере
В этом примере показано, как сформировать XML-документ на сервере и отправить его клиенту с использованием ADO:
<%' Определяемконстанты ADO.Const adopenStatic = 3Const adLockReadOnly = 1Const adCmdText = 1Const adPersistXML = 1Const adExecuteStream = &H400' созданиеобъектовDim cmd,connSet cmd = Server.CreateObject("ADODB.Command")Set conn = Server.CreateObject("ADODB.Connection")conn.Provider = "sqloledb"conn.Open "Data Source=server;Initial catalog=pubs;", "user", "password"Set cmd.ActiveConnection = conncmd.CommandType = adCmdTextcmd.CommandText = "select au_fname, au_lname, address " _ & "from authors where au_fname like 'M%' for xml auto"cmd.Properties("Output Stream") = Responsecmd.Properties("xml root") = "root"cmd.Execute , , adExecuteStreamSet cmd = nothingSet conn = nothing%> |
Здесь используется встроенная инструкция FOR XML AUTO для формирования XML-документа на SQL Server’е. В результирующем документе отсутствует корневой элемент, и для его указания используется еще одно стандартное свойство – xml root. В качестве выходного потока был использован объект Response. Результат обращения к этой ASP-страничке вы, наверное, уже давно выучили наизусть: это будет XML-документ с именами, фамилиями и адресами авторов.
Выполнение шаблона
Возьмем шаблон из первого примера раздела «Шаблоны» (код на ASP):
<%' Нужно указать это:Response.ContentType = "text/xml"' Определяем константы ADO.Const adCmdText = 1Const adExecuteStream = &H400' СоздаемобъектыDim cmd,connSet cmd = Server.CreateObject("ADODB.Command")Set conn = Server.CreateObject("ADODB.Connection")conn.Provider = "sqloledb"conn.Open "Data Source=server;Initial catalog=pubs;", "user","password"' ШаблонDim ss = "<?xml version='1.0' ?>" & _ "<my_root xmlns:sql='urn:schemas-microsoft-com:xml-sql'>" & _ "<sql:query>" & _ "select au_fname,au_lname,address from authors " & _ "where au_fname like 'M%' for xml auto" & _ "</sql:query>" & _ "</my_root>"Set cmd.ActiveConnection = conncmd.CommandType = adCmdTextcmd.CommandText = s' Диалектшаблонаcmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"cmd.Properties("Output Stream") = Responsecmd.Execute , , adExecuteStreamSet cmd = nothingSet conn = nothing%> |
Выполнение запроса XPath
С помощью ADO также можно выполнять запросы XPath, правда, пока только на аннотированных XDR-схемах. Вот скрипт на vbs, выполняющий такой запрос:
' Определяем константы ADO.Const adCmdText = 1Const adExecuteStream = &H400' СозданиеобъектовDim cmd,conn,cmdStreamDim ie Set ie = CreateObject("InternetExplorer.Application")ie.Navigate "about:blank"Set cmd = CreateObject("ADODB.Command")Set conn = CreateObject("ADODB.Connection")Set cmdStream = CreateObject("ADODB.Stream")conn.Provider = "sqloledb"conn.Open "Data Source=server;Initial catalog=pubs;", "user", "password"cmdStream.OpenSet cmd.ActiveConnection = conncmd.CommandType = adCmdText' XPath-запросcmd.CommandText = "Авторы"' Диалект XPath cmd.Dialect = "{EC2A4293-E898-11D2-B1B7-00C04F680C56}"cmd.Properties("Base Path") = "C:\Inetpub\wwwroot\server_pubs"cmd.Properties("Output Stream") = cmdStream' Аннотированнаясхемаcmd.Properties("Mapping Schema") = "schema\myschema.xml"' Шаблонтрансформацииcmd.Properties("XSL") = "\template\first_select.xsl"cmd.Properties("xml root") = "my_root"cmd.Execute , , adExecuteStreamDim strstr = cmdStream.ReadTextdoloop while ie.Busyie.Document.writeln CStr(str)ie.Document.closeie.visible = 1 |
Здесь я использовал новую аннотированную схему и шаблон трансформации.
Аннотированная схема:
<?xml version="1.0" encoding="windows-1251" ?><Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:sql="urn:schemas-microsoft-com:xml-sql" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="Авторы" sql:relation="authors"> <AttributeType name="Имя" dt:type="string" /> <AttributeType name="Фамилия" dt:type="string" /> <AttributeType name="Адрес" dt:type="string" /> <attribute type="Имя" sql:field="au_fname" /> <attribute type="Фамилия" sql:field="au_lname" /> <attribute type="Адрес" sql:field="address" /></ElementType></Schema> |
Шаблон трансформации:
<?xml version="1.0" encoding="windows-1251" ?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match = "*"> <xsl:apply-templates /> </xsl:template> <xsl:template match = "/"> <html> <body> <table border="1" style="table-layout:fixed" width="600"> <tr bgcolor="teal"> <th><font color="white">Имя</font></th> <th><font color="white">Фамилия</font></th> <th><font color="white">Адрес</font></th> </tr> <xsl:for-each select="my_root/Авторы"> <tr> <td><font color="teal"><xsl:value-of select="@Имя"/></font></td> <td><font color="teal"><xsl:value-of select="@Фамилия"/></font></td> <td><font color="teal"><xsl:value-of select="@Адрес"/></font></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template></xsl:stylesheet> |
XML-документ на стороне клиента
Предположим, ваш SQL Server работает в очень напряженном режиме, и вы не хотите нагружать его еще больше, заставляя формировать XML-документы. Можно сделать так: создать обычный рекордсет и загрузить его в формате XML в объект DOMDocument или какой-либо другой. Решение на первый взгляд здравое, однако, поработав немного с таким документом, вы поймете, что это не то. Во-первых, структура такого XML-документа задается жестко без возможности изменения. Во-вторых, схема сохраняется в формате XDR, а он уже стар и может не удовлетворять вашим потребностям. К тому же возникают проблемы с выполнением шаблонов и XPath-запросами. Для решения этих (и многих других) проблем был создан новый сервисный провайдер – SQLXMLOLEDB. Как и другие сервисные провайдеры (например, MSDataShape) он предназначен только для преобразования результирующего набора строк в нужный формат. Так как SQLXMLOLEDB ничего не знает о форматах протоколов обмена данными с SQL-серверами, он использует для этого соответствующий провайдер. К сожалению, провайдер SQLXMLOLEDB пока умеет работать совместно только с SQLOLEDB-провайдером для SQL Server, однако в будущем (по крайней мере, я очень надеюсь) он сможет работать с другими провайдерами, например, MSDAORA (провайдер для Oracle). Если такая поддержка будет встроена, у нас будет возможность получать XML-документы от источников, которые не поддерживают XML напрямую.
В режиме форматирования XML-документа на клиенте можно использовать в запросе предикат GROUP BY и агрегатные функции, недоступные в режиме формирования XML-документа на сервере (в режиме FOR XML AUTO). Как и любой другой сервисный провайдер, SQLXMLOLEDB предоставляет свой синтаксис запросов. К счастью, он не так сложен, как, например, синтаксис провайдера MSDataShape и ограничивается, по существу, следующим:
Оператор | Назначение |
FOR XML RAW | Аналогичен серверному FOR XML RAW |
FOR XML NESTED | Аналогичен серверному FOR XML AUTO |
FOR XML EXPLICIT | Аналогичен серверному FOR XML EXPLICIT |
Архитектура формирования документов на клиентской стороне изображена на рисунке 1.
Рисунок 1.
Возможность | Формирование на клиенте | Формирование на сервере |
Использование предиката GROUP BY и агрегатных функций совместно с FOR XML AUTO (NESTED) | Да | Нет |
Возможность получения одновременно нескольких рекордсетов | Нет | Да |
Задание имен элементов результирующего документа с помощью псевдонимов таблиц | Нет | Да |
Другие отличия вы можете найти в MSDN. Давайте перейдем к примерам.
Шаблон с агрегатными функциями
Ниже приведен пример использования FOR XML NESTED и атрибута client-side-xml. Шаблон возвращает документ с названиями городов и количеством авторов в каждом городе. Атрибут client-side-xml устанавливается в 1, что говорит об использовании клиентского форматирования.
<?xml version="1.0" ?><my_root xmlns:sql="urn:schemas-microsoft-com:xml-sql"> <sql:query client-side-xml="1"> select count(*) as number_of_authors,city from authors group by city order by number_of_authors desc for xml nested </sql:query></my_root> |
Формирование XML-документа на клиенте с помощью ADO
У объекта Command есть свойство ClientSideXML, которое позволяет формировать XML-документ на клиенте. Рассмотрим пример:
<%Const adCmdText = 1Const adExecuteStream = &H400Response.ContentType = "text/xml"' Creating the objectsDim conn,cmdSet conn = Server.CreateObject("ADODB.Connection")Set cmd = Server.CreateObject("ADODB.Command")conn.Provider = "sqlxmloledb"conn.Open "Data Source=server;Initial catalog=pubs;Data Provider=sqloledb", _ "user","password"Dim ss = "select count(*) as number_of_authors,city" & _ "from authors" & _ "group by city" & _ "order by number_of_authors desc" & _ "for xml nested"Set cmd.ActiveConnection = ccmd.Properties("ClientSideXML") = "True"cmd.CommandType = adCmdTextcmd.CommandText = scmd.Properties("Output Stream") = Responsecmd.Properties("xml root") = "root"cmd.Execute , , adExecuteStreamSet cmd = nothingSet conn = nothing%> |
В качестве основного провайдера задан провайдер SQLXMLOLEDB. Провайдер SQL Server’а задается с помощью строки Data Provider=sqloledb. Чтобы указать, что используется клиентское форматирование, свойство ClientSideXML установлено в true. Следует заметить, что это свойство (т.е. клиентское форматирование) можно использовать только для типа adCmdText. При вызове хранимых процедур его устанавливать нельзя.
В этом разделе мы рассмотрим способы изменения данных (удаление, добавление и правка) с помощью XML-документов. Какие достоинства у этого метода перед использованием SQL-инструкций непосредственно в шаблоне? Во-первых, апдейтаграммы намного понятнее простым пользователям или неосведомленным программистам. Хотя синтаксис написания апдейтаграмм не так уж и прост, он подчиняется обычным правилам XML и, если вы совсем не разбираетесь в SQL, апдейтаграммы – лучший выбор. Кроме этого, вы просто не имеете другой столь же эффективной альтернативы, как XML Bulk Load для загрузки больших, очень больших объемов XML-данных. Но обо всем по порядку.