Создание определяемых пользователем типов — требования

Применимо к:SQL Server

При создании определяемого пользователем типа (UDT) для установки в Microsoft SQL Server необходимо принять несколько важных решений. В большинстве случаев рекомендуется создавать определяемый пользователем тип как структуру, хотя можно создавать его и в виде класса. Определение определяемого пользователем типа должно соответствовать спецификациям для создания определяемых пользователем типов, чтобы его можно было зарегистрировать в SQL Server.

Требования к реализации определяемого пользователем типа

Для выполнения в SQL Server определяемый пользователем тип должен реализовать следующие требования в определении определяемого пользователем типа:

Определяемый пользователем тип должен указывать атрибут Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute. Использование System.SerializableAttribute является необязательным, но рекомендуется.

  • Определяемый пользователем тип должен реализовывать интерфейс System.Data.SqlTypes.INullable в классе или структуре путем создания общедоступного статического метода Null (общий в Microsoft Visual Basic). SQL Server по умолчанию учитывает значение NULL. Это необходимо, чтобы программный код, принадлежащий определяемому пользователем типу, умел распознавать значения NULL.

  • Определяемый пользователем тип должен содержать открытый статический (или общий) метод Parse , поддерживающий синтаксический анализ, и открытый метод ToString для преобразования в строковое представление объекта.

  • Определяемый пользователем формат сериализации должен реализовывать интерфейс System.Data.IBinarySerialize и предоставлять методы Read и Write .

  • Определяемый пользователем тип должен реализовывать System.Xml. Serialization.IXmlSerializable или все открытые поля и свойства должны иметь типы, которые могут быть сериализуемыми в ФОРМАТЕ XML или украшены атрибутом XmlIgnore , если требуется переопределение стандартной сериализации.

  • У объекта определяемого пользователем типа может быть только одна сериализация. Если программы сериализации или десериализации обнаружат несколько различных представлений конкретного объекта, проверка закончится ошибкой.

  • SqlUserDefinedTypeAttribute.IsByteOrdered должен иметь значение true для сравнения данных в порядке байтов. Если интерфейс IComparable не реализован, а sqlUserDefinedTypeAttribute.IsByteOrdered имеет значение false, сравнение порядка байтов завершится ошибкой.

  • Определяемый пользователем тип, заданный в виде класса, должен иметь общедоступный конструктор без аргументов. Дополнительно можно создать перегруженные конструкторы класса.

  • Определяемый пользователем тип должен предоставлять доступ к элементам данных как к общедоступным полям или процедурам свойств.

  • Открытые имена не могут быть длиннее 128 символов и должны соответствовать правилам именования SQL Server для идентификаторов, как определено в разделе Идентификаторы баз данных.

  • sql_variant столбцы не могут содержать экземпляры определяемого пользователем типа.

  • Наследуемые элементы недоступны из Transact-SQL, так как система типов SQL Server не знает об иерархии наследования между определяемыми пользователем типами. Однако можно использовать наследование при определении структуры классов и можно вызывать такие методы в реализации этих типов с помощью управляемого кода.

  • Элементы структуры или класса нельзя перегружать, кроме конструктора класса. При создании перегруженного метода ошибка не возникает при регистрации сборки или создании типа в SQL Server. Определение наличия перегруженного метода происходит во время выполнения, а не при создании типа. Класс может иметь перегруженные методы при условии, что они не вызываются. При вызове перегруженного метода возникает ошибка.

  • Все статические (или общие) члены должны объявляться как константы или как доступные только для чтения. Элементы, объявленные как статические, нельзя изменять.

  • Если для поля SqlUserDefinedTypeAttribute.MaxByteSize задано значение -1, сериализованный определяемый пользователем тип может быть таким же, как и размер большого объекта (LOB) (в настоящее время 2 ГБ). Размер определяемого пользователем типа не может превышать значение, указанное в поле MaxByteSized .

Примечание

Хотя сервер не использует его для сравнения, при необходимости можно реализовать интерфейс System.IComparable , который предоставляет один метод CompareTo. Он используется на клиенте в ситуациях, когда нужно провести точное сравнение или сортировку значений определяемого пользователем типа.

Собственная сериализация

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

bool, byte, sbyte, short, ushort, int, uint, long, ulong, float, double, SqlByte, SqlInt16, SqlInt32, SqlInt64, SqlDateTime, SqlSingle, SqlDouble, SqlMoney, SqlBoolean

Типы значений, состоящие из полей указанных выше типов, являются хорошими кандидатами для собственного формата, например структур в Visual C# (или структур , как они известны в Visual Basic). Например, определяемый пользователем тип, указанный в собственном формате сериализации, может содержать поле другого определяемого пользователем типа, которое также было указано в формате Native . Если определение определяемого пользователем типа является более сложным и содержит типы данных, отсутствуют в приведенном выше списке, необходимо указать формат сериализации UserDefined .

Собственный формат имеет следующие требования:

  • Тип не должен указывать значение для Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.MaxByteSize.

  • Все поля должны быть сериализуемыми.

  • System.Runtime.InteropServices.StructLayoutAttribute должен быть указан как StructLayout.LayoutKindSequential, если определяемый пользователем тип определен в классе, а не в структуре. Этот атрибут управляет физической компоновкой полей данных. Он заставляет члены структуры располагаться в памяти в том порядке, в каком они описаны. SQL Server использует этот атрибут для определения порядка полей для определяемых пользователем типов с несколькими значениями.

Пример определяемого пользователем типа, определенного с помощью собственной сериализации, см. в разделе Определяемый пользователем тип точки в разделе Кодирование типов User-Defined.

Сериализация, заданная пользователем

Параметр формата UserDefined для атрибута Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute предоставляет разработчику полный контроль над двоичным форматом. При указании свойства атрибута Format в качестве UserDefined в коде необходимо выполнить следующие действия:

  • Укажите необязательное свойство атрибута IsByteOrdered . Значение по умолчанию — false.

  • Укажите свойство MaxByteSizeобъекта Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.

  • Написание кода для реализации методов чтения и записи для определяемого пользователем типа путем реализации интерфейса System.Data.Sql.IBinarySerialize .

Пример определяемого пользователем типа с помощью сериализации UserDefined см. в разделе Определяемый пользователем тип валюты статьи Кодирование типов User-Defined.

Примечание

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

Атрибуты сериализации

Атрибуты определяют, каким образом сериализация используется для создания хранимых представлений определяемых пользователем типов, а также для передачи таких типов клиенту по значению. При создании определяемого пользователем типа необходимо указать атрибут Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute . Атрибут Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute указывает, что класс является пользовательским типом, и указывает хранилище для определяемого пользователем типа. При необходимости можно указать атрибут Serializable, хотя SQL Server этого не требуется.

Атрибут Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute имеет следующие свойства.

Формат
Задает формат сериализации, который может быть собственным или UserDefined в зависимости от типов данных определяемого пользователем типа.

IsByteOrdered
Логическое значение, определяющее, как SQL Server выполняет двоичное сравнение определяемого пользователем типа.

IsFixedLength
Указывает, имеют ли все экземпляры данного определяемого пользователем типа одинаковую длину.

MaxByteSize
Максимальный размер экземпляра в байтах. Необходимо указать Параметр MaxByteSize в формате сериализации UserDefined . Для определяемого пользователем типа с заданной пользовательской сериализацией MaxByteSize относится к общему размеру определяемого пользователем типа в сериализованной форме, определенной пользователем. Значение MaxByteSize должно находиться в диапазоне от 1 до 8000 или иметь значение -1, чтобы указать, что определяемый пользователем тип больше 8000 байт (общий размер не может превышать максимальный размер бизнес-объекта). Рассмотрим определяемый пользователем тип со свойством строки из 10 символов (System.Char). При сериализации определяемого пользователем типа с помощью BinaryWriter общий размер сериализованной строки составляет 22 байта: 2 байта на символ Юникода UTF-16, умноженный на максимальное число символов, плюс 2 контрольных байта, связанных с сериализацией двоичного потока. Таким образом, при определении значения MaxByteSize необходимо учитывать общий размер сериализованного определяемого пользователем типа: размер данных, сериализованных в двоичной форме, а также издержки, связанные с сериализацией.

ValidationMethodName
Имя метода, используемого для проверки экземпляров определяемого пользователем типа.

Свойство IsByteOrdered

Если свойству Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.IsByteOrdered присвоенозначение true, это гарантирует, что сериализованные двоичные данные могут использоваться для семантического упорядочения информации. Таким образом, каждый экземпляр объекта побайтно упорядоченного определяемого пользователем типа может иметь лишь одно сериализованное представление. Если операция сравнения выполняется в SQL Server сериализованных байтов, ее результаты должны быть теми же, что и при выполнении той же операции сравнения в управляемом коде. Следующие функции также поддерживаются, если isByteOrdered имеет значение true:

  • Создание индексов для столбцов этого типа.

  • Создание первичных и внешних ключей, а также ограничений CHECK и UNIQUE для столбцов этого типа.

  • Возможность использовать предложения Transact-SQL ORDER BY, GROUP BY и PARTITION BY. В этих случаях для определения порядка используется двоичное представление типа.

  • Возможность использования операторов сравнения в инструкциях Transact-SQL.

  • Сохранение вычисляемых столбцов этого типа.

Обратите внимание, что форматы сериализации Native и UserDefined поддерживают следующие операторы сравнения, если isByteOrdered имеет значение true:

  • Равно (=)

  • Не равно (!=)

  • Знак "больше" (>)

  • Знак "меньше" (<)

  • Больше или равно (>=)

  • Меньше или равно (<=)

Реализация допустимости значений NULL

Помимо задания нужных атрибутов для сборок, создаваемый класс должен также поддерживать допустимость значений NULL. Определяемые пользователем типы, загруженные в SQL Server, учитывают значение NULL, но для того, чтобы определяемый пользователем тип распознал значение NULL, класс должен реализовать интерфейс INullable. Дополнительные сведения и пример реализации допустимости значений NULL в определяемом пользователем типе см. в разделе Написание User-Defined типов.

Преобразование строк

Для поддержки преобразования строк в определяемый пользователем тип и из нее необходимо предоставить методы Parse и ToString в классе. Метод Parse позволяет преобразовать строку в определяемый пользователем тип. Он должен быть объявлен как статический (или общий в Visual Basic) и принимать параметр типа System.Data.SqlTypes.SqlString. Дополнительные сведения и пример реализации методов Parse и ToString см. в разделе Написание User-Defined типов.

XML-сериализация

Определяемые пользователем типы должны поддерживать преобразование в тип данных xml и из нее путем соответствия контракту для сериализации XML. System.Xml. Пространство имен сериализации содержит классы, которые используются для сериализации объектов в документы или потоки в формате XML. Вы можете реализовать сериализацию XML с помощью интерфейса IXmlSerializable , который обеспечивает настраиваемое форматирование для сериализации и десериализации XML.

Помимо выполнения явных преобразований из определяемого пользователем типа в xml, сериализация XML позволяет:

  • Используйте Xquery для значений экземпляров определяемых пользователем типов после преобразования в тип данных xml .

  • Использование определяемых пользователем типов в параметризованных запросах и веб-методах с собственными веб-службами XML в SQL Server.

  • Использовать определяемые пользователем типы для получения массовой загрузки XML-данных.

  • Сериализовать объекты DataSets, содержащие таблицы со столбцами определяемого пользователем типа.

Определяемые пользователем типы не сериализуются в запросах FOR XML. Чтобы выполнить запрос FOR XML, который отображает XML-сериализацию определяемых пользователем типов, явным образом преобразуйте каждый столбец определяемого пользователем типа в тип данных xml в инструкции SELECT. Можно также явно преобразовать столбцы в varbinary, varchar или nvarchar.

См. также:

Создание типа User-Defined