в SQL Server 2000 с момента выхода пакета Microsoft SQLXML 3.0, однако с тех пор прошло немало времени, а развитие технологий, связанных с Web-службами, шло очень активно. SQL Server 2005, или Yukon, представляет революционные новшества как в области поддержки XML на уровне процессора базы данных, так и в области Web-служб.

  • Устранение зависимости от Internet Information Services (IIS) путем использования системного драйвера http.sys. Это означает, что больше не будет отдельных пакетов SQLXML, которые бы «соединяли» IIS и SQL Server — вся функциональность по обработке запросов SOAP, генерации схем WSDL и т. д. находится непосредственно в SQL Server.
  • Поддержка расширений Web Services Enhancements (WSE), а именно WS-Security для обеспечения аутентификации.
  • Возможность использования сессий и транзакций в запросах SOAP.

Это далеко не полный список отличий от SQLXML 3.0, в данной статье я расскажу и о других.

Зачем базе данных XML

Начнем с того, что XML предназначен для разметки данных, а лучшего места для хранения и обработки данных, чем база данных, трудно представить. Хранить документы XML в базе данных в принципе можно было с самого момента появления XML, но что касается обработки — тут все сложнее. Так как документы XML хранились в базе данных в виде объектов CLOB — Character Large Object, работать с ними на сервере именно как с документами XML было чрезвычайно сложно. Раз уж у нас нет возможности нормально работать с документами XML на сервере, давайте и не будем с ними работать как с документами XML вообще, а будем их преобразовывать к реляционному виду и сохранять в обычных таблицах. Такой метод существует и даже в определенных случаях является оптимальным, однако он плохо применим к неструктурированным или слабоструктурируемым документам XML. В том случае когда у нас есть четко формализованная модель документа XML, достаточно просто преобразовать ее к реляционному виду, однако когда заранее неизвестно, какой структуры будут документы XML, хранимые в базе данных, сделать это практически невозможно. Мне могут возразить, что данные с неопределенной структурой вообще не стоит обрабатывать на сервере. Это действительно так, и, если вам нужно просто хранить некие документы XML, неважно что содержащие, лучшего метода, чем CLOB, не найти. Но наиболее распространены случаи, когда модель документа XML описана лишь частично: документ может содержать различные элементы расширения, это могут быть документы новых версий данного формата с новыми элементами/атрибутами и т. д. На сервере могут появляться дополнительные хранимые процедуры (или могут изменяться существующие) для работы с новыми элементами документа XML, и здесь-то и возникает необходимость в наличии определенных механизмов работы с XML на сервере.

В соответствии с требованиями времени, в SQL Server 2000 появилась функция openxml, которая позволяла преобразовывать строку в документ XML и представлять результат в виде таблицы. Однако данный метод имел определенные недостатки, связанные с простотой использования, производительностью и т. д., которые имели одно простое объяснение: XML — особый тип данных, имеющий собственные методы обработки (XPath), и не нужно пытаться эмулировать их с помощью реляционной алгебры.

Поэтому в Yukon и появился новый встроенный тип XML, встроенный процессор языка XML, поддерживающий не просто XPath 1.0, а частично XPath 2.0 и XQuery. Теперь можно ответить на вопрос, какие именно преимущества вы получаете от использования типа XML в Yukon.

  • Возможность задействовать новый мощный язык запросов для XML — XQuery.
  • Возможность индексировать поля типа XML.
  • Возможность транзакционно изменять экземпляры типа XML
  • Возможность проверять экземпляры типа XML на допустимость с помощью XML Schema

Зачем Yukon нужны Web-службы

Альтернативой разработки Web-служб в Yukon является создание Web-служб предназначенными для этого средствами, например Visual Studio .NET (ASP.NET Web-службы или WSE 2.0). Несмотря на то, что практически всю бизнес-логику теперь можно разместить в SQL Server, лучше все-таки не использовать возможность создания Web-служб в Yukon как механизма взаимодействия внешних компонентов с системой. И не потому, что в Yukon имеются проблемы с безопасностью, отсутствует гибкая настройка или это будет непроизводительно. Просто проще, выгоднее, эффективнее и правильнее создавать Web-службы с использованием Visual Studio .NET.

Зачем же в Yukon предоставляется возможность создания Web-служб? Дело в том, что механизм конечных точек (endpoints), на которых построена поддержка Web-служб в Yukon, широко используется другими подсистемами: Service Broker, Database mirroring. Возможность вызова хранимых процедур или пакетов команд через этот механизм является незначительной надстройкой, которая просто открывает новый путь взаимодействия в SQL Server. Другими словами, устраняется монополизм бинарного протокола общения с SQL Server, TDS (Tabular Data Stream). Теперь вы можете, не открывая портов SQL Server на proxy-сервере, удаленно администрировать сервер через http/https. Это замечательная и очень мощная возможность. Я не удивлюсь, если в ближайшее время появится аналог Query Analizer, построенный с использованием Web-служб.

Надеюсь, мне удалось немного прояснить ситуацию по поводу вопроса, стоящего в заголовке данного раздела, а посему предлагаю перейти к конкретным техническим аспектам поддержки XML в Yukon.

Описание конечных точек

Как я уже сказал, механизм конечных точек является частью ядра Yukon, хотя я могу предположить, что эта концепция не была заложена изначально. К сожалению, у меня сейчас нет возможности установить первую бета-версию, которая стала доступна около года назад (на выставке PDC 2003), однако я не припомню, чтобы в BOL той версии упоминались конечные точки. Более того, там не было команды create endpoint, вместо нее была команда create http endpoint, которая, как можно догадаться, создавала конечную точку по протоколу http. За последний год специалисты Microsoft очень сильно переработали механизм конечных точек, который превратился в основу взаимодействия SQL Server с внешним миром. Подсоединяясь с помощью Query Analizer или SQL Server Management Studio к Yukon, мы используем соответствующую конечную точку протокола TCP, которая позволяет выполнять команды TSQL.

Конечные точки

Синтаксис команды create endpoint довольно сложен, поэтому я разобью его на части, каждую из которых буду описывать отдельно. Базовый синтаксис таков:

CREATE ENDPOINT endPointName [AUTHORIZATION ]

STATE = { STARTED | STOPPED | DISABLED }

AS { транспорт } (

<специфичные для данного транспорта настройки>

)

FOR { протокол } (

<специфичные для данного протокола настройки>

)

  • AUTHORIZATION — указание имени учетной записи владельца конечной точки. Если имя не указано, владельцем считается учетная запись, под которой выполняется данная команда.
  • STATE — состояние конечной точки. В состоянии started сервер будет слушать порт данной конечной точки и выполнять соответствующие команды. В состоянии stopped сервер будет слушать порт, но не будет выполнять команды, возвращая клиенту ошибку. В состоянии disabled сервер не будет выполнять прослушивание по данному порту. После отключения конечной точки ее нельзя включить без перезапуска сервера.
  • AS { транспорт} — указание транспортного протокола конечной точки. На данный момент это может быть TCP или HTTP
  • FOR { протокол } — указание формата протокола приложения (или подсистемы), которая будет обрабатывать команды, приходящие через конечную точку. На данный момент это может быть: SOAP — взаимодействие осуществляется по протоколу SOAP; TSQL — взаимодействие по протоколу TDS; SERVICE_BROKER — протокол подсистемы Service Broker; DATABASE_MIRRORING — протокол для зеркалирования баз данных.

Формат для протокола TSQL в текущей версии BOL не указывается, поэтому его мы рассматривать не будем, равно как и протоколы для Service Broker и DATABASE_MIRRORING. Также я не буду описывать транспорт TCP, так как он не может использоваться для протокола SOAP, поэтому ограничимся только транспортом HTTP и протоколом SOAP (кстати, у них самые сложные настройки). Описание транспорта дано во врезке «Описание транспорта HTTP», а синтаксис для создания Web-службы приведен во врезке «Синтаксис для создания Web-службы».

Отдельно стоит подчеркнуть, хотя это должно быть видно из синтаксиса, что Web-служба может содержать один Web-метод и более либо не содержать Web-методов вообще, и при этом успешно работать (в случае, когда разрешены пакеты команд).

Естественно, что после создания конечной точки вам наверняка потребуется менять ее свойства. Как и многие другие объекты SQL Server, конечные точки поддерживают команду alter для изменения многих, но, прошу заметить, не всех своих параметров. Синтаксис этой команды не сильно отличается от команды create endpoint, поэтому его мы рассматривать не будем.

Получить список всех конечных точек можно с помощью системного представления sys.endpoints. Оно возвращает самую общую информацию обо всех конечных точках. Если вам требуется получить подробную информацию, например о Web-службах, можно воспользоваться представлением sys.http_endpoints. Соответственно, для конечных точек протокола TCP необходимо задействовать sys.TCP_endpoints. Список исключенных для использования данной конечной точкой адресов можно просмотреть в системном представлении sys.ip_exceptions.

При создании конечной точки можно столкнуться со следующими проблемами.

  • Отсутствие прав на создание конечных точек. По умолчанию только пользователи в роли serveradmin или sysadmin имеют право создавать конечную точку. Для предоставления такого права какой-либо конкретной учетной записи необходимо воспользоваться командой grant connect on endpoint, о которой пойдет разговор в следующем разделе.
  • Отсутствие прав у учетной записи, под которой запущен SQL Server, если вы создаете конечную точку, войдя на сервер не под учетной записью Windows. Резервирование пространства имен с помощью драйвера http.sys требует наличия административных полномочий, поэтому необходимо создавать конечную точку, войдя на SQL Server с помощью Windows-аккаунта, либо предоставить учетной записи, под которой запущен Yukon, административную привилегию. Учетная запись LocalSystem, под которой обычно работает сервер, такую привилегию имеет. Для предоставления пользователям, не имеющим административных полномочий, возможности создавать конечные точки необходимо явно (explicit) зарегистрировать пространство имен для драйвера http.sys с помощью системной хранимой процедуры sp_reserve_http_namespace. В этом случае пользователь, не имеющий административных прав (но которому позволено с помощью команды grant create endpoint создавать конечные точки), может создать конечную точку с помощью команды create endpoint, так как резервирование пространства имен уже было выполнено. Удалить зарезервированное пространство имен можно с помощью процедуры sp_delete_http_namespace_reservation. Еще один нюанс связан с тем, что при неявном резервировании пространство имен «принадлежит» SQL Server только на время его работы. Если сервер будет остановлен, тогда другие приложения смогут обрабатывать запросы к данному пространству имен, выполняя соответствующие регистрационные процедуры к http.sys.
  • Если конечная точка настроена для использования по протоколу ssl, необходимо указать драйверу http.sys сертификат, который будет применяться для шифрования трафика (если быть более точным, то сам сертификат не используется для шифрования — он лишь является «носителем» открытого и закрытого ключей). Указать, какой сертификат использовать при обращении к определенному адресу, можно с помощью оснастки управления IIS, либо посредством системной хранимой процедуры sp_register_ssl_certificate_for_http, куда нужно передать ip адрес и порт, а также имя сертификата. Сертификат обязан находиться в хранилище MY локального компьютера. По умолчанию там присутствуют два сертификата с названиями: servername.domainname и servername. Просмотреть список сертификатов хранилища MY локального компьютера можно с помощью утилиты certutil: certutil —store MY. Для удаления привязки сертификата к ip-адресу и порту необходимо воспользоваться хранимой процедурой sp_delete_ssl_certificate_for_http.

В качестве «источников» для Web-методов можно использовать не только собственные хранимые процедуры или функции, но и системные. Правда, тут могут возникнуть определенные проблемы, связанные с тем, что не у всех системных хранимых процедур есть информация о метаданных, которая необходима для формирования wsdl-документа, поэтому без особых настроек с подобными процедурами работать нельзя. Варианты настроек следующие.

  • Указать собственную хранимую процедуру для генерации wsdl.
  • Обернуть вызов системной процедуры в специально созданную пользовательскую хранимую процедуру.
  • Вызывать системную хранимую процедуру не как Web-метод, а с помощью пакетной команды.

Права доступа

Глубоко продуманная система разграничения прав доступа в Yukon позволяет очень гибко настраивать уровень безопасности для любого объекта базы данных, в том числе и конечных точек. Для конечных точек можно настраивать следующие права доступа.

  • Создание конечных точек для заданной на сервере учетной записи
  • Изменение (alter) всех или какой-либо конкретной конечной точки для учетной записи. Право на изменение дает также право на просмотр информации о конечной точке через представления sys.endpoints, sys.http_endpoints и т. д., а также просмотр информации о Web-методах конечной точки.
  • Соединение с конечной точкой. Соединение дает право на собственно выполнение методов конечной точки, а также на просмотр wsdl документа данной Web-службы.
  • Возможность стать владельцем конечной точки.
  • Возможность управлять (control) конечной точкой. Это как бы объединяющее право, заключающее в себе права на изменение, соединение, возможность стать владельцем конечной точки, а также права на удаление (drop).

Владелец (owner) конечной точки и пользователь в роли sysadmin имеют все права на конечную точку.

Синтаксис команды разграничения прав доступа (в сокращенном варианте) таков:

{GRANT/DENY/REVOKE}

{CREATE/ALTER ANY/ALTER ON/CONNECT ON/TAKE OWNERSHIP ON}

ENDPOINT TO

  • GRANT/DENY/REVOKE — предоставление, запрещение или отзыв права соответственно.
  • CREATE — право на создание конечной точки.
  • ALTER ANY — право на изменение любой конечной точки.
  • ALTER ON — право на изменение конкретной точки.
  • CONNECT ON — право на соединение.
  • TAKE OWNERSHIP ON — право быть владельцем конечной точки.

Приведу пример предоставления права на изменение параметров конечной точки HelloFromYukon для учетной записи test:

grant alter on endpoint::HelloFromYukon to test

Наиболее важным правом, с точки зрения пользователей Web-службы, является право соединения с конечной точкой, однако его одного недостаточно. При использовании Web-службы перед клиентом встают другие проблемы, связанные с аутентификацией, передачей учетных данных на сервер и выбором безопасного транспорта. Обо всем этом в следующем разделе.

Безопасность и аутентификация

К обеспечению безопасности разработчики Yukon должны были подойти особенно внимательно: в наше время факт взлома какой бы то ни было системы определяется только временем. Web-службы с точки зрения безопасности являются дополнительной возможностью атаки для хакеров, поэтому без разработки особых мер предосторожности здесь просто не обойтись. Какие же средства для обеспечения безопасности имеет Yukon?

  • Для доступа к Web-службе необходимо иметь учетную запись в операционной системе на компьютере, где расположен SQL Server. Это может быть локальная или доменная учетная запись.
  • Передача пароля и его хешированного представления ни в каком виде не осуществляется открыто. Учетные данные пользователя всегда шифруются либо на транспортном уровне (ssl), либо на уровне протокола (ntlm, kerberos).
  • Учетная запись, под которой вы подключаетесь к Web-службе в случае интегрированной аутентификации, или учетная запись SQL Server, данные которой переданы в заголовке пакета SOAP в случае смешанной аутентификации, должны иметь доступ на соединение с конечной точкой.

Краеугольным камнем безопасности является аутентификация — процесс передачи и проверки удостоверения пользователя. Под удостоверением обычно понимают имя пользователя и пароль, хотя это могут быть smart-карты, отпечатки пальцев и т.д. Конфиденциальность паролей никоим образом не должна подвергаться риску, поэтому в Yukon для протоколов, которые к перехвату паролей неустойчивы, использование шифрования на транспортном уровне с помощью ssl является обязательным. Это, безусловно, создает некоторые проблемы для пользователей Web-службы и усложняет поддержку, однако существенно снижает риск перехвата удостоверений.

Ниже приводятся типы аутентификации, которые поддерживаются конечными точками в Yukon.

  • Basic — базовая аутентификация, при которой имя пользователя и пароль передаются в заголовках http-пакетов. Пароль при этом не шифруется и присутствует в чистом виде в кодировке base64. Для данного типа аутентификации использование ssl является обязательным.
  • Digest — дайджест-аутентификация, при которой пароль пользователя передается в хешированном виде. По уровню конфиденциальности паролей этот тип мало чем отличается от предыдущего, так как атакующему все равно, действительно ли это настоящий пароль или только хеш от него: перехватив удостоверение, он все равно получает доступ к конечной точке. Для данного типа аутентификации использование ssl является обязательным.
  • Integrated — интегрированная аутентификация, при которой клиент и сервер общаются для выяснения подлинности друг друга с помощью протоколов NTLM или Kerberos. Этот тип аутентификации защищен от перехвата удостоверений пользователей, поэтому для него не требуется протокол ssl. Только при использовании данного типа аутентификации можно работать по http, во всех остальных случаях необходимо использовать https.

Кроме настройки типа аутентификация на уровне конечной точки, у нас есть возможность настроить тип учетной записи на уровне каждого отдельного Web-методa. Тип учетной записи может быть следующим.

  • Windows — в данном случае учетные данные пользователя, которые были получены при соединении с конечной точкой, должны представлять пользователя в SQL Server. Если такой учетной записи не существует, клиенту возвращается ошибка.
  • Mixed — в этом случае учетные данные пользователя, полученные в процессе соединения с конечной точкой, отбрасываются. Вместо них используются имя пользователя и пароль, которые переданы в заголовке soap-сообщения. Таким образом, в этом режиме пользователю не обязательно иметь учетную запись в SQL Server, которая была бы основана на учетной записи Windows. В таком режиме можно использовать всего одну учетную запись Windows для авторизации на уровне конечной точки для всех клиентов и специальные учетные данные для применения конкретных Web-методов. Так как имя пользователя и пароль передаются в заголовке в открытом виде, для данного режима использование ssl является обязательным.

Итак, перечислим действия, которые необходимо предпринять администратору, чтобы разрешить вызывать метод hello_world нашей Web-службы HelloFromYukon пользователю домена vasja.

  1. Создать учетную запись на сервере: create login [domainvasja] from windows.
  2. Создать учетную запись пользователя в тестовой базе данных для учетной записи сервера: create user vasja for login [domainvasja].
  3. Предоставить право на исполнение хранимой процедуры hello_world: grant execute on hello_world to vasja.
  4. Предоставить право на соединение с данной конечной точкой: grant connect on endpoint::HelloFromYukon to [domainvasja]

Описание SOAP-сообщений

Если вы не любите копаться в деталях, не признаете SOAP и планируете писать клиентские программы только с помощью Visual Studio .NET, которая скрывает используемые при обмене с сервером форматы путем генерации proxy-класса, этот раздел не для вас. В нем мы будем рассматривать структуру SOAP-запросов и SOAP-ответов, допустимые заголовки и содержание wsdl-документа. Так как многое в Yukon (по крайней мере, в данной версии) в области форматов сообщений было взято без каких-либо серьезных изменений из пакета SQLXML, советую прежде ознакомиться с соответствующей документацией.

В данном разделе приняты префиксы для пространств имен, перечисленные в таблице 1.

Структура сообщений

Надо сказать, что описания входных и выходных сообщений в виде XML Schema были существенно переработаны с точки зрения увеличения строгости. Так, например, если в SQLXML присутствовало всего три схемы в wsdl-документе, то в Yukon их число возросло до девяти. Естественно, при этом wsdl-документ стал куда более громоздким и сложным для восприятия. Общее описание схем приведено в таблице 2, а описание структуры — во врезке «Описание структуры сообщений SOAP». При описании форматов сообщений я буду использовать общепринятую систему квалификаторов множеств узлов, где: + — один и более, * — нуль и более, ? — нуль или один, если ничего не указано — ровно один.

Заголовки

Любое SOAP-сообщение может иметь заголовки. Заголовки — это элементы в разделе SOAP: Header SOAP-сообщения. Заголовки различных типов описывают аспекты SOAP-сообщения, т.е. информационные элементы, которые напрямую не относятся к основному информационному содержанию сообщения. Заголовки обрабатываются независимо от сообщения, они не влияют на то, что будет сделано, но управляют тем, как это будет сделано.

Заголовки SOAP-сообщений в Yukon введены в первую очередь для предоставления дополнительной информации о клиенте, подобной той, что предоставляется протоколом TDS. Все рассматриваемые ниже элементы находятся в пространстве имен http://schemas.microsoft.com/ sqlserver/2004/SOAP/Options, схема которой может быть получена из wsdl-документа web service. Ни один из перечисленных в таблице 3 заголовков не является обязательным.

WSDL

WSDL-документы предназначены для формального описания контрактов, которые используются Web-службами для взаимодействия с клиентами. WSDL-документы сродни idl-файлам технологии COM, где описывались интерфейсы, методы этих интерфейсов и параметры методов.

WSDL-файлы во многом опираются на схемы XSD, которые мы рассмотрели в предыдущем разделе. В данном разделе будут рассмотрены особенности поддержки WSDL в Yukon.

Зачем вообще могут понадобиться WSDL-документы? Если предстоит формировать пакеты SOAP вручную, в сущности, они и не нужны. Однако подобный подход к использованию Web-служб можно считать неправильным. В XXI веке принято применять средства автоматической генерации пакетов SOAP, которые позволяют задействовать Web-службы как обычные объекты в памяти приложения. К подобным средствам можно отнести генератор клиентского посредника, который входит в .NET Framework, SOAP Toolkit, генератор клиентского посредника ATL и другие. Для них WSDL-документы являются обязательными. WSDL-документ предоставляет всю необходимую информацию для генерирования кода и успешного взаимодействия с Web-службой, а именно: используемые протоколы, физические адреса и порты, доступные методы, параметры и типы параметров этих методов и многое др. Если вы разрабатываете собственную Web-службу, поддержка WSDL на сегодня фактически считается обязательной. Подробное описание использования WSDL можно найти во врезке «Типы WSDL-файлов»

Использование Web-службы

Так как архитектура Web-служб основана на открытых стандартах, при корректной реализации серверного кода клиентами Web-службы в идеале может быть кто угодно. На практике клиентские средства доступа к Web-службе всегда обладают определенными недостатками. Хотя подобных недостатков в стандартном генераторе клиентского кода .Net Framework 1.1 немного, к сожалению, он практически не может использоваться с Web-службами Yukon. В данном разделе я рассмотрю особенности работы с Web-службами с помощью Visual Studio .NET 2003, SOAP Toolkit и Visual Studio .NET 2005. Меньше всего проблем возникает с Visual Studio .NET 2005 (хотя я использовал только бета-версию), с нее и начнем.

Visual Studio .NET 2005

Генератор клиентского кода Visual Studio .NET 2005 прекрасно работает с WSDL-файлом Yukon. Последовательность действий такова. С помощью диалогового окна Add Reference или утилиты wsdl.exe мы генерируем клиентский код, далее создаем экземпляр proxy-класса, присваиваем его свойству Credentials соответствующее значение (это обязательно) и вызываем Web-метод.

Необходимо учесть, что при использовании простого WSDL-документа результаты выборки будут представлены в виде массива экземпляров типа XMLElement, а скалярные значения — в виде экземпляров шаблона System.Nullable(of T). При использовании сложного WSDL-документа результаты выборки будут представлены в виде массива объектов типа System.Data.DataSet — содержащим собственно данные, Integer — содержащим результирующий код (элемент SqlResultCode) и SqlRowCount — содержащим количество выбранных строк. Скалярные значения будут представлены экземплярами из пространства имен System.Data.SqlTypes.

Если вы указали аутентификацию MIXED при создании конечной точки, тогда вам необходимо передавать с каждым SOAP-запросом информацию об удостоверении пользователя в виде SOAP-заголовка — Security. Этот заголовок является частью спецификации WS-Security; используя механизм XML сериализации, создать его довольно просто (пример реализации данного заголовка с помощью IXMLSerializable можно найти в BOL).

Для использования заголовка необходимо изменить стандартный код, генерируемый средой разработки: нужно добавить к proxy-классу элемент типа Security, указать атрибут SOAPHeader для методов proxy-класса, в конструктор которого передать название элемента заголовка. После создания экземпляра proxy-класса, но перед вызовом соответствующего метода, необходимо заполнить поля этого заголовка. Тип пароля — http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText

Кроме этого, так как необходимо использовать SSL для аутентификации MIXED, требуется статическому свойству Net.ServicePointManager.CertificatePolicy присвоить экземпляр следующего класса:

Friend Class MyCertValidation

Implements Net.ICertificatePolicy

Public Function CheckValidationResult(ByVal srvPoint As System.Net.ServicePoint,

ByVal certificate As System.Security.Cryptography

.X509Certificates.X509Certificate,

ByVal request As System.Net.WebRequest, ByVal certificateProblem As Integer) As

Boolean Implements System.Net.ICertificatePolicy.CheckValidationResult

Return True

End Function

End Class

Данный класс переопределяет всего одну функцию, которая возвращает true. Это позволяет использовать сертификаты SSL, которые не являются доверенными.

Visual Studio .NET 2003

В старой версии среды разработки дела с использованием Web-служб Yukon обстоят хуже. .Net Framework 1.1 не умеет работать со сложной версией WSDL-документа SQL Server 2005. При генерации самого proxy-класса ошибок не возникает, однако при его создании инициируется исключение — «Method couldn?t be reflected». Единственная возможность работать с Web-службой заключается в использовании простого WSDL-документа. Однако и здесь все не так просто. Скалярные методы вызываются прекрасно, но методы, возвращающие набор строк, представляют результаты в виде объектов типа XMLDocument. Для набора строк XMLElement содержит XML в формате diffgram, который, однако, не может использоваться для создания DataSet. Дело в том, что формат встроенной схемы, которая возвращается вместе с набором, непонятен классу DataSet из .NET Framework 1.1 и ниже. Отказаться от генерации встроенной схемы можно (см. синтаксис команды create endpoint), но формат diffgram устроен таким образом, что наличие информации о схеме данных для него является обязательным. Выход из ситуации только один — самому вручную или автоматически создавать схему для DataSet на клиенте.

Конечно, это не самый удобный и правильный метод. При любом изменении в Web-методе придется изменять код клиента, дабы структура DataSet отвечала соответствующей структуре результирующего набора строк. Однако, если структура сообщений изменяться не будет, можно сгенерировать типизированный DataSet, и тогда работа с результатами вызова Web-метода станет существенно проще.

SOAP Toolkit

SOAP Toolkit не имеет стандартных конвертеров, которые позволяли бы работать со сложным WSDL-документом Yukon. Опять же в данной ситуации может помочь простой WSDL-документ.

В листинге 3 приведен пример вызова нашего метода.

Как можно видеть из кода, достоинства сценариев, использующих SOAP Toolkit, заключается в том, что не нужно предварительно генерировать proxy-класс — весь код инфраструктура создает «на лету», в момент вызова метода mssoapinit. С другой стороны, мы теряем строгую типизацию, поэтому результирующий SOAP-документ представлен в «сыром» виде — в качестве объектов DOM. Для дальнейшей работы с результатами требуется использовать относительно сложный путь написания XPath-запросов. Однако для тестирования я считаю этот метод идеальным.

Заголовки в SOAP Toolkit, которые могут понадобиться для авторизации, сессий или транзакций, могут быть добавлены с помощью реализации интерфейса IHeaderHandler. Примеры соответствующего кода можно найти в MSDN.

Сессии

Архитектура Web-служб в чистом виде является stateless, т.е. не имеет состояния. Однако многие инфраструктуры вроде ASP.NET Web Services позволяют создавать statefull (имеющие состояние) Web-службы. Web-службы Yukon также могут хранить состояние, однако с точки зрения архитектуры их отличие от ASP.NET Web Services заключается в том, что Yukon хранит идентификаторы сессий в заголовках SOAP-пакетов, а не в cookies.

Сессия является внутренним, ядерным объектом сервера. Список всех сессий можно просмотреть с помощью динамического представления sys.dm_exec_sessions. Время жизни сессии может быть задано при создании конечной точки. По умолчанию оно составляет 60 секунд. Создание сессии производится с помощью посылки заголовка SQLSession:

где sqloptions префикс пространства имен http://schemas.microsoft.com/ sqlserver/2004/SOAP/Options.

После этого сервер наряду с обычными результатами выборки возвращает тот же самый заголовок, но уже с атрибутами sessionId — идентификатор сессии и timeout — время жизни сессии. Идентификатор сессии кодируется в форму base64 и в дальнейшем используется при следующих запросах. Идентификатор сессии строго привязан к учетным данным клиента Windows, который инициировал сессию. Запрещается использовать тот же самый идентификатор под другими учетными данными. Сессия действительна до тех пор, пока не истечет время ее жизни или пока клиент сам не завершит ее. Завершение сессии достигается путем посылки заголовка SQLSession с атрибутом terminate:

Запрос на завершение сессии может не содержать ничего, кроме заголовка. Если сервер успешно закрывает сессию, он присылает ответное сообщение с точно таким же заголовком и точно такими же значениями атрибутов.

Для использования сессий в своем приложении придется формировать заголовок SQLSession самостоятельно. В случае SOAP Toolkit, как я уже говорил выше, это можно сделать с помощью интерфейса IHeaderHandler. Для Visual Studio все значительно проще: в BOL есть пример данного заголовка.

Транзакции

Транзакционный вызов Web-методов — это очень мощная возможность, позволяющая избавиться от многих проблем при реализации бизнес-логики. Реализация транзакций в Yukon для конечных точек SOAP имеет некоторые ограничения.

  • Транзакции работают в контексте сессий.
  • Транзакции работают только с пакетными запросами (т.е. как таковые вызовы Web-методов нельзя обрамлять в транзакции).

Для начала транзакции необходимо инициировать сессию, передать заголовок environmentChangeNotifications и собственно начать транзакцию (простую или распределенную) в коде TSQL пакетного запроса (см. листинг 4).

В данном пакетном запросе мы открываем транзакцию, выбираем все строки из таблицы test базы данных test, говорим, что необходимо начать новую сессию, а также сообщаем серверу о том, что хотим получать все данные об изменении контекста транзакции. На подобный запрос сервер должен возвратить, кроме результатов выборки и заголовка сессии, еще и структуру SqlTransaction внутри элемента sqlbacthResult примерно такого содержания:



AQAAADkAAAA=

Begin

где sqltransaction — префикс пространства имен http://schemas. microsoft.com/sqlserver/ 2004/SOAP/types/SqlTransaction, значение текстового узла элемента Descriptor — идентификатор транзакции и тип уведомления о транзакции — Begin.

Контекст транзакции жестко привязан к идентификатору сессии. Если идентификатор сессии отличается от того, при котором данный контекст был создан или идентификатор сессии не задан вообще, а также если запрос выполняется под другим удостоверением, генерируется ошибка SOAP.

Присоединиться к существующему контексту транзакции можно с помощью атрибута transactionDescriptor элемента sqlSession, значение которого является идентификатором данной транзакции:

Завершить транзакцию можно двумя способами: либо подтвердить (commit) ее, либо отменить (rollback). В обоих случаях сервер должен прислать ответное сообщение с элементом SqlTransaction, который бы содержал дескриптор транзакции и соответствующий тип: при отмене транзакции — rollback, при подтверждении — commit. Кроме этого, транзакция может быть отменена при закрытии сессии.

Транзакции (как и сессии и другие заголовки) необходимо задавать самостоятельно. В BOL есть примеры подобных заголовков с использованием XML-сериализации.

Заключение

Описанные в статье механизмы, конечно же, еще рано применять в серьезных проектах, однако вероятность того, что часть из них будет отсутствовать в финальной версии, очень мала. Если вы все-таки планируете долгосрочную перспективу перехода на новые технологии, данный материал, я надеюсь, будет для вас полезным.


Описание транспорта HTTP

AS HTTP (

PATH = ?url?

, AUTHENTICATION =( { BASIC | DIGEST | INTEGRATED } [,...n])

, PORTS = ({CLEAR | SSL} [,... n])

[ SITE = {?*? | ?+? | ?webSite? },]

[, CLEAR_PORT = порт для http ]

[, SSL_PORT = порт для https ]

[, AUTH_REALM = { ?realm? | NONE } ]

[, DEFAULT_LOGON_DOMAIN = {?domain? | NONE } ]

[, RESTRICT_IP = { NONE | ALL } ]

[, COMPRESSION = { ENABLED | DISABLED } ]

[, EXCEPT_IP = ( { <4-part-ip> | <4-part-ip>: } [,...n] )

)

  • PATH — задает URL-путь, идентифицирующий данную конечную точку. Например, если указывается /simple, то данная Web-служба будет доступна по адресу http://server/simple, где server — имя сайта.
  • AUTHENTICATION — задает тип аутентификации, который будет использоваться при регистрации в SQL Server. Может быть basic, digest, integrated или их комбинацией.
  • PORTS — типы портов для прослушивания. Может быть: clear — используется http; ssl — используется https; либо можно указать оба.
  • SITE — название сайта в данной системе.
  • CLEAR_PORT — конкретный номер порта для протокола http.
  • SSL_PORT — конкретный номер порта для протокола https.
  • AUTH_REALM — значение соответствующего заголовка, который будет возвращаться клиенту как часть взаимодействия по методу Digest.
  • DEFAULT_LOGON_DOMAIN — учетная запись домена по умолчанию, которая используется, если указана аутентификация Basic.
  • RESTRICT_IP — совместно с EXCEPT_IP задает адреса портов, с которых можно обращаться к конечной точке. Возможны следующие варианты:

    RESTRICT_IP = all — в этом случае никто не имеет доступа к конечной точке, за исключением адресов, перечисленных в параметре EXCEPT_IP.

    RESTRICT_IP = none — в этом случае все имеют доступ к конечной точке, исключая адреса, перечисленные в параметре EXCEPT_IP.
  • COMPRESSION — указывает, будет ли сервер выполнять упаковку данных по алгоритму gzip, или нет. Упаковка выполняется только в том случае, если указано значение enabled, а также если клиент сообщил серверу с помощью заголовков http, что поддерживает кодирование gzip.

Синтаксис для создания Web-службы

FOR SOAP(

[ { WEBMETHOD [ ?namespace? .] ?method_alias?

( NAME = ?three.part.name?

[, SCHEMA = {NONE | STANDARD | DEFAULT}]

[, FORMAT = { ALL_RESULTS | ROWSETS_ONLY | NONE }]

[, LOGIN_TYPE = { MIXED | WINDOWS } ]

)

} [,...n] ]

[ BATCHES = { ENABLED | DISABLED } ]

[ , WSDL = { NONE | DEFAULT | ?sp_name? } ]

[ , SESSIONS = { ENABLED | DISABLED } ]

[ , SESSION_TIMEOUT = int ]



[ , DATABASE = { ?database_name? | DEFAULT }

[ , NAMESPACE = { ?namespace? | DEFAULT } ]

[ , SCHEMA = { NONE | STANDARD } ]

[ , CHARACTER_SET = { SQL | XML }]

)
  • WEBMETHOD — указывает пространство имен и название Web-методa. Данное значение используется для однозначной идентификации Web-метода и передается в заголовке SOAPAction. Если пространство имен не задано, будет использовано пространство имен Web-службы, которое задается параметром NAMESPACE (описан далее). У Web-метода есть свой набор параметров:
    • NAME — название хранимой процедуры или пользовательской функции. Имя должно состоять из трех частей: названия базы, названия схемы и названия объекта. Если на момент создания Web-метода данного объекта не существует, будет выдано предупреждение, однако Web-метод будет успешно создан.
    • SCHEMA — определяет, будет ли отправляться схема XML в каждом ответном сообщении. Может принимать значения: default — значение берется из глобального параметра schema для всей Web-службы; standard — схема будет отдаваться в каждом ответном сообщении; и none — схема не будет отдаваться клиенту в ответном сообщении. По умолчанию используется default.
    • FORMAT — тип формата вывода результатов Web-метода. Это могут быть следующие значения: all_results — выводятся все результаты выполнения Web-метода, а именно: результирующий набор строк, количество выбранных строк и сообщения об ошибках и предупреждениях; rowsets_only — выводится только результирующий набор строк; none — результат выводится в том виде, какой отдается сервером, т.е. не выполняется никаких преобразований к xml-виду. По умолчанию используется all_results.
    • LOGIN_TYPE — тип учетной записи, которая используется для вызова Web-метода. Может принимать значения: windows — интегрированная аутентификация Windows; mixed — смешанная аутентификация SQL Server и Windows. Если при установке сервера смешанная аутентификация была запрещена или при настройке транспорта не был указан ssl, режим mixed применять запрещается. По умолчанию используется Windows.
  • BATCHES — определяет, может ли Web-служба принимать запросы на исполнение пакетов команд. При указании значения enabled становится возможным посылать любые команды TSQL без создания каких-либо дополнительных Web-методов. При указании значения default, которое является значением по умолчанию, данная возможность отпадает.
  • WSDL — указывает, будет ли генерироваться описание Web-службы в формате wsdl или нет. Если стандартная схема по каким-либо причинам не подходит, можно указать хранимую процедуру, которая будет использоваться для генерации wsdl.
  • SESSIONS — позволяет объединять различные запросы soap, как часть одной сессии, если указывается значение enabled. Значение disabled, которое является значением по умолчанию, отключает сессии.
  • SESSION_TIMEOUT — задает время в секундах, по истечении которого после последнего запроса клиента сессия soap будет уничтожена.
  • DATABASE — база данных по умолчанию. Если указано значение default, будет использоваться база данных по умолчанию для данной учетной записи.
  • NAMESPACE — пространство имен для Web-службы. Если указано значение default, используется стандартное предопределенное пространство http://tempuri.org.
  • SCHEMA — указывает, будет ли генерироваться XML Schema для Web-службы.
  • CHARACTER_SET — указывает, будут ли включаться в результирующее сообщение символы с некорректными для XML кодами.

Описание структуры сообщений SOAP

Запрос

Формат вызова Web-метода не изменился, однако у клиента появилась новая возможность выполнять пакетные команды. Структура запроса при этом выглядит так:





любое TSQL выражение



*









Атрибуты элемента SqlParameter описывают точные свойства параметра.

  • Название параметра (указывать обязательно).
  • Тип параметра (указывать обязательно).
  • Длина строкового представления параметра (указывать обязательно).
  • Направление (direction) — входной или входной и выходной.
  • Другие свойства, описание которых можно найти в BOL.

Значение параметра задается в элементе Value, который не имеет конкретного типа по схеме XML. Его тип необходимо указывать непосредственно в сообщении с помощью атрибута xsi:type.

Элементы пакетной команды BatchCommands и Parameters должны быть в пространстве имен http://schemas.microsoft.com/sqlserver/2004/SOAP. Элементы SqlParameter и Value — в пространстве имен http://schemas.microsoft.com/ sqlserver/2004/SOAP/types/SqlParameter.

Пример пакетного запроса приведен в листинге 1.

Ответ

Ответное сообщение имеет более существенные отличия от SQLXML. В нем может появляться один или более из приведенных ниже объектов.

  • Результирующие объекты выборки. Под объектами выборки понимаются xml-документы, полученные в результате запросов for xml либо сериализованные в xml (а точнее, в формат diffgram, который поддерживается классом DataSet из .Net Framework) реляционные строки.
  • Количество выбранных строк.
  • Код возврата в случае вызова хранимой процедуры или пользовательской функции.
  • Значения выходных параметров.
  • Сообщения об ошибках и предупреждениях.
  • Статус транзакции.

Вот как выглядит описание этих объектов в формате схемы XML:



















Как уже говорилось выше, в результирующем потоке появилось два новых элемента: SqlRowCount и SqlTransaction. Общая структура ответного сообщения такова:









Value*

Здесь:

  • MethodName — имя Web-метод. Для пакетных запросов это sqlbatch.
  • Method — префикс пространства имен Web-метода. Для нашего Web-метода hello_world пространством имен является http://tempuri.org. Для пакетных запросов — http://schemas.microsoft.com/sqlserver/2004/SOAP.
  • OutputParam — значения выходных параметров.

Элемент MethodNameResult может содержать один или более объектов, описанных в типе SqlResultStream. Рассмотрим, в каких случаях будет использоваться тот или иной объект.

SqlRowSet — используется в случае, когда результирующий поток содержит результаты реляционной выборки. Этот элемент описан в схеме так:





minOccurs=»0» processContents=»lax»/>

minOccurs=»0» processContents=»lax»/>



Он может содержать любое количество элементов из пространства имен http://www.w3.org/2001/XMLSchema, а также любое количество элементов из пространства имен urn:schemas-microsoft-com:xml-diffgram-v1. Первое пространство имен принадлежит стандарту схемы XML и означает, что в результирующий поток может включаться XSD-схема. Это поведение регулируется с помощью параметра schema конечной точки и Web-метода. Второе пространство имен означает, что результирующая выборка будет представлена в формате diffgram, который поддерживается стандартным классом System.Data.DataSet из .Net Framework. Например, результатом выполнения листинга 2 будет следующая diffgram (несущественные части сообщения удалены):







10

adventure-worksarryj

M





SqlXml — используется в случае, если применяются for xml-запросы, которые возвращают xml. Нет необходимости преобразовывать результаты этих запросов в diffgram, потому что они сами представляют собой xml-документы. Описание элемента SqlXml представлено в схеме следующим образом:









Элемент SqlXml может содержать любой элемент из любого пространства имен. В качестве примера возьмем тот же самый листинг 2, только с несколько измененным запросом: в конце добавим for xml auto. Вот результат:



LoginID=»adventure-worksarryj» Gender=»M»/>

SqlMessage — все программные ошибки, не относящиеся к инфраструктуре конечных точек, возвращаются в данном элементе. Структура элемента довольно проста, поэтому ее описание здесь не приводится. Непрограммные ошибки описаны в следующем разделе.

Ошибка

В большинстве случаев Yukon не возвращает ошибки soap при наличии ошибок в запросах SQL, параметрах хранимых процедур и т.д. Soap-ошибки возвращаются только в следующих случаях.

  • Пакет SOAP сформирован неверно.
  • Возникли ошибки во время обработки запроса SOAP.
  • Для вызова Web-метода использовалась неверная учетная запись.
  • Другие ошибки, не относящиеся к обработке http-запросов и выполнению собственно команд T-SQL.

В случае подобного рода ошибок Yukon возвращает 500-й код ошибки http и элемент env:Fault в ответном SOAP-сообщении. Soap-ошибка возвращается в формате soap 1.1, однако более подробная информация об ошибке может быть получена через внутреннюю структуру в формате soap 1.2, которая находится в элементе detail. Структура ошибки описана в листинге 3.


Типы WSDL-файлов

Рассмотрим фрагмент синтаксиса создания и изменения конечной точки:

[ , WSDL = { NONE | DEFAULT | ?sp_name? } ]

При создании конечной точки, если не задано никаких специальных параметров или указано значение NONE, поддержка wsdl будет отключена. При указании значения DEFAULT SQL Server 2005 будет использовать стандартный генератор wsdl-документов, который может создавать два типа документов: простые и сложные. Сложный wsdl-документ описывает все детали и тонкости возвращаемых SQL Server документов XML. В таком документе присутствует обширная XSD-схема, очень подробно описывающая все серверные типы в формате XSD. Получающаяся в результате XSD-схема настолько сложна, что многие автоматические средства генерации клиентского кода не могут обработать подобный WSDL-документ. Как ни странно, к таким средствам относятся стандартный генератор .NET Framework 1.1 и SOAP Toolkit. Для подобных «устаревших» средств SQL Server генерирует wsdl-документ в простом формате. Основное отличие заключается в том, что результирующий документ XML имеет тип не SqlResultStream, а простой тип xsd:any.

Вот фрагмент простого wsdl-документа нашей Web-службы:

























Как можно заметить, элемент hello_worldResponse содержит лишь один элемент hello_worldResult, который может содержать любое количество каких угодно элементов.

В простой схеме имеется еще много изменений в объявлениях серверных типов, однако мы не будем углубляться в такие дебри: каждый желающий может сравнить эти файлы самостоятельно.

Сложный wsdl-документ можно получить путем обращения к Web-службе: http://localhost/yukon/hello?wsdl. Данную строку можно набрать в любом браузере, например в Internet Explorer. Он загрузит WSDL-документ и отобразит его как обычный XML-файл. Для получения простого документа необходимо обратиться к серверу так: http://localhost/yukon/hello?wsdlsimple.

Все документы генерируются «на лету», т.е. SQL Server не кэширует их и не вычисляет заранее.

Если вас по каким-либо причинам не устраивает стандартный генератор wsdl-документов, вы можете написать свой. Пользовательский генератор — это обычная хранимая процедура с определенной сигнатурой, которая должна возвращать набор с одной строкой и одним полем. Значение этой ячейки будет трактоваться как WSDL-документ. Сигнатура хранимой процедуры такова:

CREATE PROCEDURE (

@endpointID as int,

@isSSL as bit,

@host as nvarchar(256),

@queryString as nvarchar(256))

as

где:

  • endpointID — идентификатор конечной точки;
  • sSSL — параметр, который означае, был ли использован SSL;
  • host — название сервера;
  • queryString — параметр запроса.

Данная процедура вызывается, когда происходит обращение по адресу конечной точки с указанием какого-либо параметра (параметр — это то, что следует после знака вопроса в строке запроса). Например, для нашей Web-службы мы можем написать следующее: http://localhost/yukon/hello?some-info. Строка после знака вопроса (some-info) будет передана в хранимую процедуру в качестве параметра queryString. По соображениям совместимости и наглядности рекомендуется начинать название параметра со слова wsdl, например: http://localhost/yukon/hello?wsdl,some-info.

Обычно подобные хранимые процедуры пишутся на управляемом коде с использованием всех возможностей обычных языков (таких, как VB.NET или C#) и общей языковой среды — CLR. Пример подобной процедуры можно найти в BOL, но можно написать ее с использованием простого TSQL.

Стандартные генераторы схем, которые могут понадобиться при написании собственного генератора, являются также хранимыми процедурами. Информацию о них можно просмотреть с помощью следующего запроса:

select * from sys.system_objects where name like ?sp_http_generate_wsdl%?

Параметры системных хранимых процедур можно просмотреть с помощью представления sys.system_parameters. Сигнатуру пользовательской функции генератора я, кстати, узнал из такого запроса:

select * from sys.system_parameters where [object_id] = object_id(?sp_http_generate_wsdl_defaultcomplexorsimple?)

Рекомендую выполнить этот запрос перед тем, как писать собственный генератор, потому что я сильно сомневаюсь, что сигнатура хранимой процедуры в будущих версиях Yukon не изменится.


Примечание автора.

Вся приведенная в статье информация относится ко второй бета-версии SQL Server 2005, поэтому третья бета-версия или финальный продукт могут отличаться по функциональности или деталям реализации. Будьте внимательны и сверяйтесь с BOL.


Mенеджер проекта в компании ЕСИСТЕМА. Имеет сертификаты MCSD, MCAD