Поделиться через


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

Область применения: SQL Server

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

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

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

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

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

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

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

  • UDT должен реализовать 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 , если UDT определен в классе, а не в структуре. Этот атрибут управляет физической компоновкой полей данных. Он заставляет члены структуры располагаться в памяти в том порядке, в каком они описаны. SQL Server использует этот атрибут для определения порядка полей для определяемых пользователем типов с несколькими значениями.

Пример определяемого пользователем определяемого пользователем типа с собственной сериализацией см. в статье "Точка UDT" в кодировании определяемых пользователем типов.

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

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

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

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

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

Пример определяемого пользователем определяемого пользователем сериализации см. в разделе "UDT" в кодировании определяемых пользователем типов.

Примечание.

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

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

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

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

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

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

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

MaxByteSize
Максимальный размер экземпляра в байтах. Необходимо указать MaxByteSize с форматом сериализации UserDefined . Для определяемого пользователем типа UDT с заданной сериализацией MaxByteSize ссылается на общий размер определяемого пользователем типа UDT в сериализованной форме, как определено пользователем. Значение MaxByteSize должно находиться в диапазоне от 1 до 8000 или иметь значение -1, чтобы указать, что UDT больше 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. Определяемые пользователем UDT, загруженные в SQL Server, имеют значение NULL, но для распознавания значения NULL класс должен реализовать интерфейс INullable . Дополнительные сведения и пример реализации значения NULL в определяемом пользователем типе см. в разделе "Кодирование определяемых пользователем типов".

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

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

Сериализация XML

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

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

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

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

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

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

Определяемые пользователем типы не сериализуются в запросах FOR XML. Чтобы выполнить ЗАПРОС FOR XML, отображающий сериализацию XML определяемых пользователем объектов, явно преобразуйте каждый столбец UDT в тип данных XML в инструкции SELECT. Можно также явно преобразовать столбцы в varbinary, varchar или nvarchar.

См. также

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