Главная » Microsoft SQL Server, Базы данных » Обзор типов CLR в SQL Server

0

С помощью среды .NET Framework для SQL Server 2005 можно создать пять типов объектов:

?               хранимые процедуры;

?               функции;

?               триггеры;

?               пользовательские типы;

?               пользовательские консолидации.

Первые три являются расширением функциональности, доступной в предыдущих версиях SQL Server с помощью языка Т-SQL. Двойники этих объектов на языке Т-SQL остались доступными и в версии SQL Server 2005 были даже улучшены. В конце главы будет показано, когда следует использовать типы CLR, а когда испытанные объекты Т-SQL. Оставшиеся два типа объектов базы данных могут быть созданы исключительно с использованием интеграции CLR — это пользовательские типы и пользовательские консолидации. Эти типы появились только в версии SQL Server 2005. В этом разделе мы рассмотрим общие черты всех пяти типов объектов CLR SQL Server, а затем отдельно остановимся на характеристиках каждого из них.

Атрибуты типов .NET интеграции CLR

Ранее в этой главе была описана концепция домена приложения среды .NET Framework. В SQL Server домен приложения определяется владельцем объекта. Владельцем объекта является администратор базы данных. Это значит, что доменом приложения, или базовым уровнем изоляции программного кода для интеграции CLR, являются все объекты, принадлежащие одному и тому же пользователю или роли в текущей базе данных.

Дополнительная Дополнительная информация об администраторах базы данных приведена в

информация главе 40.

Объекты CLR в SQL Server всегда содержат элементы метаданных, называемые атрибутами. Атрибуты в среде .NET используются для определения назначения конкретной сборки, класса, метода, свойства, события или типа. Например, атрибут может быть использован для определения метода как CLS-совместимого. Забегая вперед, в материал глав, посвященных Web-службам, можно сказать, что атрибут можно использовать для маркировки метода как Web-службы для объектов, находящихся за пределами домена приложения данного метода.

Именованные атрибуты типов объектов SQL Server более корректно называют пользовательскими атрибутами .NET Framework. Разработчики интеграции CLR в компании Microsoft для интерпретации этих атрибутов создали управляемые расширения класса из пространства имен System. Attribute. Пользовательские атрибуты вычисляются, когда тип импортируется в SQL Server и когда компилируется в среду выполнения. В объектах SQL Server пользовательские атрибуты определяют, какой из пяти типов объектов базы данных находится в источнике. Пользовательские атрибуты также содержат всю информацию, необходимую SQL Server для импорта объекта при развертывании. Все сопутствующие пользовательские атрибуты также вычисляются, когда для объекта выполняется инструкция T-SQL CREATE OBJECT после его импорта.

А     Помещайте блоки пользовательских атрибутов непосредственно перед программ-

ным кодом, к которому они относятся. Блок пользовательских атрибутов может УЙ быть также помещен в начало файла источника, если задан модификатор атрибу- та, указывающий, в каком месте он должен быть применен. Однако в этом случае Проверено связь между атрибутом и программным кодом, к которому он относится, будет не такой очевидной для того, кто будет сопровождать незнакомый код. Шаблоны объектов SQL Server в Visual Studio 2005 всегда используют первый метод. Каждый из атрибутов заключается в пару угловых скобок (< >) и содержит имя атрибута, за которым следуют обязательные позиционные параметры, а затем необязательные аргументы. Атрибуты объектов SQL Server хорошо документированы.

Ниже приводится несколько примеров пользовательских атрибутов объектов базы данных на языке VB.NET в том виде, в каком они сгенерированы шаблонами Visual Studio 2005. <SqlProcedure()> _

<SqlTrigger(Name:="name"Target:="Table", Event:="FOR UPDATE")> _ <SqlFunction()> _

<Serializable()> _

<SqlUserDefinedType(Format.Native)> _

<SqlMethod> _

<SqlFacet> _

<Serializable()> _

<SqlUserDefinedAggregate(Format.Native)> _

Как будет показано позже, установка списков аргументов может оказаться технически трудоемкой. Отметим, что атрибут Sql Procedure не имеет аргументов, и остальные атрибуты типов SQL Server, если явно не заданы, получают значения по умолчанию.

В шаблоне для пользовательских типов и консолидаций также присутствует атрибут Serializable (упорядочиваемость). Это не пользовательский, а системный атрибут; он используется во время выполнения, а не загрузки. Под упорядочиваемостью понимается то, что объект, которому присваивается этот атрибут, может записывать свое состояние в базу данных или некоторое другое постоянное хранилище, а затем считывать его оттуда. Упорядочиваемость является важным атрибутом объектов пользовательских типов и консолидаций, которые должны быть материализованы и индексированы в базе данных. Неупорядочивае- мые типы могут быть не отсортированы, и их использование в некоторых случаях может оказаться невозможным. Например, неупорядочиваемые типы при использовании в качестве вычисляемых столбцов базы данных могут оказаться не проиндексированными, не отсортированными, не сгруппированными, не поддающимися сравнению и не живучими.

Пользовательские типы могут содержать два члена для атрибутов: SqlMethod, который унаследован из объекта SqlFunction, и SqlFacet, который используется для описания возвращаемого типа UDT.

Пользовательские атрибуты объектов SQL Server служат прототипом для конструктора классов этого типа. Естественно, это не единственный способ, которым атрибуты могут использоваться в среде .NET Framework. Вспомним, что экземпляры класса создаются с помощью метода new этого класса. Например, явный вызов метода создания нового экземпляра хранимой процедуры никогда нельзя увидеть в программном коде пользователя. Однако когда создается хранимая процедура CLR, на самом деле CLR вызывает конструктор класса каждый раз, когда эта процедура выполняется.

Общие характеристики типов CLR в SQL Server

На самом деле среда выполнения достойна рассмотрения как общая характеристика всех пяти типов объектов SQL Server. В кратком обзоре среды .NET Framework, с которого началась настоящая глава, была описана механика среды выполнения CLR: исходный программный код предварительно компилируется на язык Microsoft Intermediate Language, независимый от исходного языка программирования. Когда на данный код выполняется ссылка в среде выполнения, компилятор JIT загружает код MSIL в память в виде машинных инструкций. Самый обычный код .NET компилируется в инструкции, которые может выполнить операционная система Windows. Интеграция CLR подразумевает, что компилятор JIT читает код MSIL из таблиц базы данных, а не из файлов библиотек .dll. Этот компилятор создает инструкции, которые SQL Server хранит, распределяет и обрабатывает в своем пространстве памяти. Это позволяет использовать SQL Server не только для управления традиционным ядром, кэшем данных и процедур и постоянным источником проблем MemToLive, но и в качестве полноценной среды выполнения с интенсивной обработкой данных.

Изящество решения состоит в том, что мало что происходит при вызове компонента CLR, если сама среда выполнения не была активизирована на сервере. По умолчанию интеграция CLR отключена. Чтобы ее включить, нужно использовать утилиту SQL Server Surface Area Configuration Tool или хранимую процедуру T-SQL sp_conf igure:

exec sp_configure 1clr enabled’, 1 reconfigure with override

После включения среды выполнения CLR при вызове компонента интеграции CLR при первом использовании он будет скомпилирован компилятором JIT в память. Полученные машинные инструкции будут доступны в памяти до тех пор, пока их срок жизни не истечет или не будет остановлена служба SQL Server. При создании первого экземпляра объекта производительность несколько падает, что связано с его компиляцией. После этого объект остается в качестве двоичного элемента в ядре, подобно любой встроенной функции или типу данных.

Было бы наивно ожидать, чтобы функции CLR могли сравниться по производительности с системными. В то же время вполне реалистично, чтобы функции CLR работы с датой-временем в запросах, обрабатывающих множество строк, выполняли гораздо больше, чем обычные функции Т-SQL, используемые в предложении WHERE. Функции CLR не смогут по быстродействию сравниться со встроенными функциями, однако в контексте работы с множествами данных по производительности они все-таки намного ближе к встроенным, чем к функциям T-SQL.

Типы данных

Перед тем как исследовать аргументы атрибутов и прочие уникальные характеристики каждого из типов объектов SQL Server, некоторое внимание следует уделить одной общности между ними. Это типы данных. В манере, не менее неправдоподобной, чем обслуживание податливой средой выполнения SQL Server, основанной на приоритетах среды выполнения CLR, CLR также должна свести воедино “родные” типы данных SQL Server и .NET Framework. Числовые типы данных .NET рассматриваются как типы значений. Типы значений обычно обслуживаются в области памяти стека вызова. Символьные типы данных .NET рассматриваются как объекты, на которые имеются ссылки. Они всегда используют память, отделенную от стека вызова, — она еще известна под названием куча управляемого объекта.

Типы данных, унаследованные от объекта (а все в куче управляемого объекта унаследовано от объекта общего базового класса), впечатляют. Такие типы содержат члены, в том числе свойства и методы, чтобы сделать манипуляции более гибкими, чем примитивные типы данных значений. Тип данных может быть перемещен или упакован из стека вызова в кучу объекта, если та определена, или использован, как если бы он имел свойства, методы или поля. Упаковка может быть явной и неявной.

Иногда полезно перемещать примитив в управляемую кучу, чтобы его поведе- Совет   ние было похоже на поведение объекта. Этот процесс называется упаковкой. В

качестве классического примера базы данных, в которой может использоваться упаковка, можно привести базу, в которой даты хранятся в виде символьных литералов или в которой интегральные значения должны сравниваться со столбцами, содержащими символьные данные. В то же время при сравнении десятков тысяч строк, основанных на столбце с типом ссылки, в коде CLR производительность будет значительно падать, если данные на самом деле имеют тип значения. При этом не всегда совершенно очевидно, что конкретная операция доступа к данным будет страдать от побочного эффекта упаковки. Обычно вопросы, касающиеся упаковки, всплывают после накопления некоторого опыта работы с интеграцией CLR. Тогда становится возможным идентифицировать типы CLR, которые по необъяснимым причинам работают медленнее других типов CLR. Чтобы определить, произошла ли упаковка, можно посмотреть на код MSIL. Читателям, заинтересовавшимся данным вопросом, будет небезынтересно узнать, что в состав Visual Studio 2005 входит утилита дизассемблирования кода MSIL, которая называется ildasm.exe.

Работа с типами данных CLR имеет свои сложности. Одной из самых больших проблем является то, что типы данных .NET Framework не распознают пустые значения. В SQL Server значение null указывает на то, что атрибут сущности не имеет определенного значения; таким образом, по умолчанию в стандарте ANSI SQL такое значение, среди прочего, не может участвовать в операциях сравнения, а также в консолидациях. Примитивные типы данных в модели программирования CLR лишены этой концепции. К счастью, существует коллекция типов данных, доступная в пространстве имен System.Data.SqlTypes, которая отображается непосредственно на типы данных SQL Server. Все эти типы реализуют интерфейс iNullable. Это совершенно не значит, что сложности отображения типов данных между средой .NET и SQL Server на этом исчерпываются, но, тем не менее, это пространство имен может оказать существенную помощь. К примеру, если вам нужно сравнить десятичное значение базы данных с точностью, превышающей 28 знаков, с оперативным измерением, хранимым в десятичном значении .NET, необходимо будет преобразовать тип decimal среды .NET в тип SqlDecimal, чтобы избежать вероятных исключений при выполнении программы. В сходном, но полностью противоположном сценарии значение SqlMoney может быть переполнено при сравнении с десятичным значением .NET, которое пришло от поставщика, отличного от SQL Server.

С точки зрения программиста, при написании только “безопасного" CAS-совместимого кода CLR-компоненты базы данных, использующие типы из пространства имен System. Data. SqlTypes, позволят установить более прозрачные отношения между компонентами интеграции CLR и базой данных. К тому же использование SqlTypes для данных, которые происходят из базы данных, позволят программному коду выполняться существенно быстрее, поскольку типы данных .NET Framework будут неявно преобразовываться в SqlTypes средой выполнения CLR при отправке в базу данных. В противном случае для выполнения операций сравнения и присвоения типы данных .NET должны преобразовываться явно. В табл. 27.1 приведены “родные” типы данных SQL Server в порядке, в котором они перечислены в пространстве имен System. Data. SqlDBType, соответствующем System. Data. SqlTypes, и эквивалентные им встроенные типы данных среды .NET Framework. Отдельные позиции будут сопровождаться комментариями автора.

Таблица 27.1. Типы данных SQL Server/CLR/.NET

“Родной” тип SQL Server

Тип интеграции CLR в SQL Server

Тип CLR .NET Framework

Комментарии

Bigint

Sqllnt64

Int64

Binary, Varbimary, Varbinary (max)

SqlBytes,

SqlBinary

Byte []

Bit

SqlBoolean

Boolean

Char, Nchar, Nvarchar, Nvarchar (max), sysname, Varchar, Varchar(max)

SqlChars,

SqlString

String, Char[]

В .NET Framework все символы принадлежат таблице Unicode

DateTime,

SmallDateTime

SqlDateTime

Datetime

Decimal, Numeric

SqlDecimal

Decimal

Разные диапазоны значений: в SQL Server и SqlDecimal +/-КГ38+1, а в .NET несколько меньше: +/- 7,9228162514264337593543950335 Е+ 28

Float

SqlDouble

Double

В SQL мантисса масштабируемая; по умолчанию float (53)

Image

Byte [], Bitmap

Все двоичные объекты поставляются в базу данных и из нее в потоках как SQLBinary

Int

Sqllnt32

Int32

Money, Smallmoney

SqlMoney

Decimal

Диапазон SqlMoney составляет 2~63 с точностью за одной десятитысячной

Ntext, Text

Real

SqlSingle

Single

В SQL-92 эквивалентом типа real является float (24)

Smallint

Sqllntl6

Intl6

SQL_variant

Object

Table

ISqlResultSet

Timestamp

Byte []

Tinyint

SqlByte

Byte

Пользовательский тип

Сборка пользовательских типов должна присутствовать на стороне клиента, чтобы приложение знало о них

“Родной”тип SQL

Тип интеграции

Тип CLR .NET

Комментарии

Server

CLR в SQL Server

Framework

Uniqueidentifier

SqlGuid

Guid

XML

SqlXML

Источник: Нильсен, Пол. Microsoft SQL Server 2005. Библия пользователя. : Пер. с англ. — М. : ООО “И.Д. Вильямс”, 2008. — 1232 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии