ПОДДЕРЖКА XML ДАННЫХ В ADO.NET 2.0: ОБРАБОТКА XML ДАННЫХ ИЗ SQL SERVER 2005

Bob Beauchemin
DevelopMentor

October 2004

Перевод статьи. Автор: Максим Стародубцев
Первоисточник: http://msdn.microsoft.com/en-us/library/ms971534.aspx (English)

Введение

Одним из существенных изменений в Microsoft SQL Server 2005 является включение XML данных. Этот тип данных является основным классом типов, как, например, INT или VARCHAR, и SQL Server 2005 позволяет осуществлять запросы и обработку этого типа данных с помощью ряда функций для работы с XML. Также существует поддержка для хранения коллекций схем XML в базе данных, включая схему проверки базы данных. Кроме того, SQL Server 2005 существенно расширяет функциональность состава XML (SELECT … FOR XML диалекты), расширяет OpenXML() XML декомпозицию функции, и предоставляет новую функцию nodes() с данными XML для декомпозиции на более мелкие составляющие. С учетом всей этой новой и расширенной функциональности XML на сервере базы данных неудивительно, что поставщик данных SqlClient в Microsoft ADO.NET 2.0 также был улучшен. Также есть изменения в ADO.NET DataSet для поддержки DataColumn с типом XML, и "точек интеграции" между System.Data и System.Xml были расширены. В этой статье я буду исследовать использование типа данных XML в SQL Server 2005 на стороне клиента.

Есть два типа XML вывода, которые может создать SQL Server 2005. Команда SELECT * FROM AUTHORS FOR XML AUTO создает поток XML, а не одноколоночный, однострочный набор строк. Этот тип вывода не изменился по сравнению с SQL Server 2000. XML поток вывода является в SQL Server Query Analyzer как одноколоночный, однострочный набор строк только из-за ограничений в утилите Query Analyzer. Вы можете отличить этот поток от "нормального" столбца по его уникальному идентификационному имени "XML_F52E2B61-18A1-11d1-B105-000805F49916B". Это название, впрочем, является показателем для основного TDS (Table Data Stream, таблицы потока данных – сетевой формат SQL Server) анализатора, т.е. столбец должен быть передан в потоке клиенту, а не быть отправленным как обыкновенный набор строк. Существует специальный метод, SqlCommand.ExecuteXmlReader, для получения этого специального потока клиентом. В SQL Server 2005 SELECT ... FOR XML диалект был улучшен многими способами. Упомянем лишь некоторые из них:

1. Существует новый, простой в использовании FOR XML PATH режим, который Вы можете использовать в большинстве случаев, когда Вам необходим режим FOR XML EXPLICIT в SQL Server 2000.

2. Вы можете создать столбец XML-данных в дополнение к потоку, используя директиву TYPE.

3. Вы можете вкладывать FOR XML выражения.

4. SELECT … FOR XML могут создать XML документы такие же как XML фрагменты с использованием директивы ROOT.

5. Вы можете вставить в начало потока стандартную схему XSD.

Вы получаете ваше первое указание на то, что XML в настоящее время является классом основных типов реляционных баз данных, ссылающийся на реляционные перечислимые типы данных в ADO.NET 2.0. System.Data.DbType и System.Data.SqlDbType содержат дополнительные значения для DbType.Xml и SqlDbType.Xml, соответственно.

Появился также новый класс SqlXml в пространстве имён System.Data.SqlTypes. Этот класс действует как фабрика для экземпляров класса XmlReader в вершине иерархии типов XML. Я продемонстрирую, что это значит с помощью простого кода. Скажем, что у меня есть таблица в SQL Server, которая выглядит примерно так:

CREATE TABLE xmltab (
  id INT IDENTITY PRIMARY KEY,
  xmlcol XML)

Столбец метаданных, который возвращается, когда я просматриваю DataTable, созданный GetSchemaTable, правильно определяет столбец:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Xml;

void GetXMLColumn {
//Generic Coding... " article for shows how to
// get a connection string from a config file
string s = GetConnectStringFromConfigFile("xmldb");
using (SqlConnection conn = new SqlConnection(s))
using (SqlCommand cmd = new SqlCommand(
       "select * from xmltab", conn))
 {
  conn.Open();
  SqlDataReader rdr = cmd.ExecuteReader();
  DataTable t = rdr.GetSchemaTable();

  while (rdr.Read())
    {
      SqlXml sx = rdr.GetSqlXml(1);
      XmlReader xr = sx.CreateReader();
      xr.Read(); 
      Console.WriteLine(xr.ReadOuterXml());
    }
 }
}

Выглядит как и любой другой тип, встроенный в SQL Server. Заметим, что ". NET тип" в этом столбце XmlReader, и в .NET это выглядит точно так же, как любой XML, загружаемый из файла или созданный классом XmlDocument. Использование столбца XML-данных в качестве параметра хранимой процедуры или параметризованной функции в ADO.NET 2.0 столь же просто…

Использование поддержки XML-схемы на клиенте

SQL Server 2005 поддерживает строго типизированный XML, а это означает, что XML должен соответствовать XML-схеме или множеству XML-схем. Эта поддержка разрешена при использовании коллекций XML-схем в SQL Server. Коллекции XML-схем определяются как и любой другой объект SQL Server, и XML-схемы, хранятся в SQL Server. Использование T-SQL команды DDL CREATE и коллекции XML-схемы выглядит так:

CREATE XML SCHEMA COLLECTION books_xsd
AS
-- one or more XML schemas here
GO

CREATE TABLE typed_xml (
  id INT IDENTITY PRIMARY KEY,
  -- require books_col content to be schema-valid
  books_col XML(books_xsd)
)
-- validated here
INSERT typed_xml VALUES('<!-- some document -->')
-- validated here too
UPDATE typed_xml
  SET books_col.modify('<!-- some XQuery DML -->')
  WHERE id = 1

Когда вы используете строго типизированный XML данных внутри SQL Server 2005 со стороны клиента, проверка выполняется на сервере, а не на клиенте. Так, например, если вы используете метод AddARow, показанный в предыдущем примере, чтобы добавить строку в typed_xml таблицу, данные передаются по сети на SQL Server до выполнения проверки. Хотя требуется мало работы, всё же возможно получать XML-схемы из коллекции XML-схем SQL Server, и скрывать их в клиенте для достижения клиентской проверки. Это может сэкономить некоторые полные просмотры, предупреждая пользователя или веб-сервис из отправляемой недействительной схемы XML вашему клиенту для хранения в SQL Server, но есть два момента/уточнения, которые должны быть рассмотрены. Во-первых, основываясь на XML схеме информация извлекается из SQL Server как полагается на любых кэшированных клиентских метаданных. Это возможно, когда кто-то должен изменить коллекцию схемы с использованием T-SQL команды ALTER XML SCHEMA, или даже отказался от коллекции схемы и воссоздали её, в результате чего ваши клиентские проверки бесполезны. Вы можете защититься от сюрпризов, используя новое EVENT NOTIFICATION команды CREATE/ALTER/DROP XML SCHEMA DDL. Вы бы затем использовали собственный код для контроля службы Service Broker, аналогичной при использовании SqlNotificationRequest с запросом уведомлений. EVENT NOTIFICATIONs ново в SQL Server 2005, но аналогично с Query Notifications, рассматриваемое в моей предыдущей статье “ Query Notifications в ADO.NET 2.0”. Во-вторых, иметь в виду, что даже, если вы делаете проверку схемы XML на стороне клиента, SQL Server будет повторять вашу проверку на сервере.

Не существует способа указать SQL Server "Я знаю, что этот экземпляр XML-схемы SQL Server является действительным, не беспокойся проверить её самостоятельно". Для создания проверки XML-схемы на стороне клиента вы можете получить информацию о SQL Server XML SCHEMA COLLECTION, используя T-SQL функцию xml_schema_namespace(). Это требует имя коллекции XML-схемы и имя схемы базы данных, поскольку коллекции XML-схемы видимы в схеме базы данных. Мы можем жёстко запрограммировать их в программу или извлечь их из набора строк метаданных на стороне клиента. Используя ранее метод SqlDataReader GetSchemaTable или новый класс SqlMetaData, можно было легко получить имя коллекции схемы, связанной с определённым столбцом. Вот короткий пример кода:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.Sql;

void GetCollectionInfo {
// get a connection string from a config file
string s = GetConnectStringFromConfigFile("xmldb");
using (SqlConnection conn = new SqlConnection(s))
using (SqlCommand cmd = new SqlCommand(
       "select books_col from typed_xml", conn))
{
  conn.Open();
  // fetch only SQL Server metadata
  SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.SchemaOnly);

  SqlMetaData md = rdr.GetSqlMetaData(0);
  string database = md.XmlSchemaCollectionDatabase;
  string schema = md.XmlSchemaCollectionOwningSchema;
  string collection = md.XmlSchemaCollectionName;
}
}

После того как Вы поняли какую коллекцию XML-схемы получать, вы можете воспользоваться T-SQL функцией для её получения в клиентское XmlSchemaSet. Заметим, что этот пример демонстрирует также то, как получить фрагмент, используя XmlReader. Это необходимо потому, что может быть больше, чем одна XML-схема в XML SCHEMA COLLECTION; функция xml_schema_namespace вернёт все XML- схемы в коллекции как фрагмент.

При наличии XmlSchemaSet мы можем интегрировать клиентский код проверки XML в нашу Add процедуру, и вуаля! проверка на стороне клиента. Хотя проверка XML-схемы на стороне клиента не является чем-то, что требует каждое приложение, но неплохо бы знать, что это доступно, если ваше приложение нуждается в ней. XML-схемы также порождаются при использовании новой опции SQL Server 2005 XMLSCHEMA в SELECT ... FOR XML, как это:

   SELECT * FROM authors FOR XML AUTO, ELEMENTS, XMLSCHEMA

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

Заключение

Я описал использование новый тип XML и новые FOR XML возможности потребления XML из Microsoft SQL Server в Microsoft ADO.NET SqlClient, а также о том, как, используя SqlClient, вставлять XML в таблицы SQL Server. На самом деле функциональность XML улучшена в DataSet, чего я не упомянул; об этом будет рассказано в предстоящей серии статей по ADO 2.0 DataSet расширениям. Вы можете узнать больше об использовании SQL Server XML данных в MSDN online статье Шанкара Пала, Марка Фусселла и Ирвина Долобовского ”Поддержка XML в Microsoft SQL Server 2005”; больше о расширении к SELECT ... FOR XML можно прочитать в MSDN online статье Майкла Риса “Что нового в FOR XML в Microsoft SQL Server 2005”; больше о System.Xml в .NET 2.0 можно прочитать в статье Марка Фусселла “Что нового в System.Xml для Visual Studio 2005 и .NET Framework 2.0 Release”. Можно смело сказать, что XML интегрирован с ADO.NET 2.0 и SqlClient на многих уровнях; интеграция моделей данных всегда компактна.