XML в MS SQL Server 2000 и технологиях доступа к данным | Аннотированные схемы | Дальше » |
По своей структуре это обычные XSD-схемы, в которых допускаются специальные аннотации, задающие их привязку к сущностям реляционной структуры: таблицам, полям, первичным и внешним ключам, отношениям между таблицами и т.д., благодаря чему данные, хранящиеся на SQL Server, можно привести к желаемой XSD- структуре и запрашивать затем как XML-документ (XPath, XQuery). В VS .Net входит удобный редактор XSD-схем, позволяющий собирать их, натаскивая drag-n-drop'ом элементы, атрибуты, типы и т.д. из панели инструментов. Редактор имеет две панели: одна показывает традиционный XML-код схемы, а другая - ее реляционный эквивалент в виде таблиц и связей между ними. При переключении происходит автоматическая валидация схемы, доступная также из меню (Schema -> Validate). В нем есть цветовое выделение синтаксических конструкций, intelisense-подсказки и многие другие приятные вещи. Итак, с помощью этого замечательного редактора я создаю вид моего XML-документа, который будет содержать, допустим, информацию по клиентам и сделанных ими заказах. <?xml version="1.0" encoding="utf-8" ?> <xs:schema id="XMLSchema1" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="Клиент"> <xs:sequence> <xs:element name="Адрес" type="Адрес" /> <xs:element name="Заказы" type="Заказы" /> </xs:sequence> <xs:attribute name="Имя" type="xs:string" /> <xs:attribute name="Должность" type="xs:string" /> <xs:attribute name="Фирма" type="xs:string" /> </xs:complexType> <xs:complexType name="Адрес"> <xs:sequence> <xs:element name="Страна" type="xs:string" /> <xs:element name="Город" type="xs:string" /> <xs:element name="Улица_дом" type="xs:string" /> <xs:element name="Индекс" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:complexType name="Заказы"> <xs:sequence> <xs:element name="Заказ" type="Заказ" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="Заказ"> <xs:sequence> <xs:element name="Дата" type="xs:date" /> <xs:element name="Стоимость" type="xs:float" /> </xs:sequence> </xs:complexType> </xs:schema>
Теперь, чтобы по этой схеме представить данные из SQL Server, сопоставим их элементам и атрибутам при помощи аннотаций - см. рис.4 - для поддержки которых в схеме делается ссылка на соответствующее пространство имен (xmlns:ms="urn:schemas-microsoft-com:mapping-schema"). <?xml version="1.0" encoding="utf-8" ?> <xs:schema id="SQLSchema1" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ms="urn:schemas-microsoft-com:mapping-schema"> <xs:annotation> <xs:appinfo> <ms:relationship name="CustOrds" parent="Customers" parent-key="CustomerID" child="Orders" child-key="CustomerID" /> </xs:appinfo> </xs:annotation> <xs:complexType name="Клиент"> <xs:sequence> <xs:element name="Адрес" type="Адрес" ms:is-constant="1" /> <xs:element name="Заказы" type="Заказы" ms:is-constant="1" /> </xs:sequence> <xs:attribute name="Имя" type="xs:string" ms:field="ContactName" /> <xs:attribute name="Должность" type="xs:string" ms:field="ContactTitle" /> <xs:attribute name="Фирма" type="xs:string" ms:field="CompanyName" /> </xs:complexType> <xs:complexType name="Адрес"> <xs:sequence> <xs:element name="Страна" type="xs:string" ms:field="Country" /> <xs:element name="Город" type="xs:string" ms:field="City" /> <xs:element name="Улица_дом" type="xs:string" ms:field="Address" /> <xs:element name="Индекс" type="xs:string" ms:mapped="false" /> </xs:sequence> </xs:complexType> <xs:complexType name="Заказы"> <xs:sequence> <xs:element name="Заказ" type="Заказ" minOccurs="0" maxOccurs="unbounded" ms:relation="Orders" ms:relationship="CustOrds" /> </xs:sequence> </xs:complexType> <xs:complexType name="Заказ"> <xs:sequence> <xs:element name="Дата" type="xs:date" ms:field="OrderDate" /> <xs:element name="Стоимость" type="xs:float" ms:field="Freight" /> </xs:sequence> <xs:attribute name="Номер" type="xs:string" ms:field="OrderID" /> </xs:complexType> <xs:element name="Клиент" type="Клиент" ms:relation="Customers" /> </xs:schema>
Аннотация sql:relation используется для отображения узла на
таблицу. Она не поддерживается в тэгах определения типа, т.е.
только в xs:element и xs:attribute, поэтому нам пришлось ввести
в схему элемент составного типа "Клиент": <xs:element name="Клиент" type="Клиент" ms:relation="Customers" />. Вложенные
элементы соответствуют записям дочерней таблицы, поэтому для
них требуется еще задать ms:relationship. Отношения между таблицами в
терминах родительской и дочерней таблиц (parent / child) и полей, по которым
устанавливается связь (parent-key /
child-key), определяются как атрибуты элемента <ms:relationship> в разделе
определения аннотаций <xs:annotation>, <xs:appinfo>. Затем это
отношение можно использовать, чтобы вложить дочерние записи
внутрь родительского элемента <xs:element name="Заказ" type="Заказ"... ms:relation="Orders" ms:relationship="CustOrds"/>. Если
вложенный элемент не соответствует никакой дочерней таблице, а
несет чисто контейнерную функцию (как, например, Адрес), то он помечается атрибутом ms:is-constant="1":
<xs:element
name="Адрес" type="Адрес" ms:is-constant="1"/>. Аннотация ms:field
привязывает XML-узел к полю таблицы. Она не требуется, когда
название атрибута совпадает с названием поля. Непривязанные
атрибуты также не допускаются. Если мы не планируем брать
значение узла из БД, но в силу каких-либо причин не можем
исключить его из схемы, его нужно пометить аннотацией ms:mapped="false":
<xs:element
name="Индекс" type="xs:string" ms:mapped="false" />. От is-constant она отличается тем, что узел
вообще исключается из результирующего
XML-документа. <?xml version="1.0" encoding="utf-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ms="urn:schemas-microsoft-com:mapping-schema" id="SQLSchema2"> <xs:annotation> <xs:appinfo> <ms:relationship name="Начальник-Подчиненный" parent="Employees" parent-key="EmployeeID" child="Employees" child-key="ReportsTo" /> </xs:appinfo> </xs:annotation> <xs:element name="Сотрудник" type="Тип_Сотрудник" ms:relation="Employees" ms:key-fields="EmployeeID" ms:limit-field="ReportsTo" /> <xs:complexType name="Тип_Сотрудник"> <xs:sequence> <xs:element name="Сотрудник" type="Тип_Сотрудник" ms:relation="Employees" ms:key-fields="EmployeeID" ms:relationship="Начальник-Подчиненный" ms:max-depth="3" /> </xs:sequence> <xs:attribute name="ID_сотрудника" type="xs:ID" ms:field="EmployeeID" ms:hide="true" /> <xs:attribute name="Имя" type="xs:string" ms:field="FirstName" /> <xs:attribute name="Фамилия" type="xs:string" ms:field="LastName" /> </xs:complexType> </xs:schema>
Он взят из документации к SQLXML 3.0. Таблица Employees
содержит записи по сотрудникам и связана сама с собой, т.е. в
поле ReportsTo для каждого сотрудника указывается EmployeeID
его начальника. static void Annotated_XPathQuery_SQLXML() { ... cmd.CommandText = "Клиент[Адрес/Страна='Spain' or Адрес/Страна='France']"; cmd.SchemaPath = "..\\Schemas\\SQLSchema1.xsd"; cmd.CommandType = SqlXmlCommandType.XPath; cmd.RootTag = "Клиенты"; XmlDocument xml = new XmlDocument(); xml.Load(cmd.ExecuteStream()); ... }
В Скрипте 10, как и в предыдущем примере (Скрипт 9), на SQL Server посылается XPath-запрос, однако теперь данные рассматриваются через призму выбранной аннотированной схемы (указывается в свойстве SqlXmlCommand.SchemaPath) и трактуются в соответствии с задаваемой ею структурой. В данном случае запрос выбирает всех клиентов из Испании и Франции и сделанные ими заказы. Встроенной поддержкой XPath (а также XQuery) SQL Server в настоящее время не располагает, поэтому XPath по дороге превращается в то, что ему более понятно, а именно - в SQL-запрос. Если быть совсем точным, то в запрос типа FOR XML EXPLICIT. Ради любопытства можете открыть Profiler и посмотреть его для Скрипта 10 (здесь я его приводить не буду, потому что он занял бы еще как минимум страницу). Поддерживается подмножество стандартного синтаксиса XPath в части осей, функций и операторов. Отрадно, что каждым SQLXML веб-релизом это подмножество расширяется. |
XML в MS SQL Server 2000 и технологиях доступа к данным | Аннотированные схемы | Дальше » |