MS SQL Server 9 “Yukon”. Интеграция с .NET

%d0%a1%d1%82%d1%80%d0%be%d0%ba%d0%be%d0%b2%d0%be%d0%b5%20%d0%b2%d1%8b%d1%80%d0%b0%d0%b6%d0%b5%d0%bd%d0%b8%d0%b5,%20%d0%ba%d0%be%d1%82%d0%be%d1%80%d0%be%d0%b5%20%d1%83%d0%ba%d0%b0%d0%b7%d1%8b%d0%b2%d0%b0%d0%b5%d1%82%20%d0%bb%d0%be%d0%ba%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b9%20%d0%b8%d0%bb%d0%b8%20%d1%81%d0%b5%d1%82%d0%b5%d0%b2%d0%be%d0%b9%20%d0%bf%d1%83%d1%82%d1%8c%20%d0%ba%20%d1%84%d0%b0%d0%b9%d0%bb%d1%83%20%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b8.%20%d0%9c%d0%be%d0%b6%d0%bd%d0%be%20%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b6%d0%b0%d1%82%d1%8c%20%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be%20%d0%be%d0%b4%d0%bd%d0%be%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b5%20%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b8.%20%d0%92%d1%81%d0%b5%20%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b8,%20%d0%be%d1%82%20%d0%ba%d0%be%d1%82%d0%be%d1%80%d1%8b%d1%85%20%d0%b7%d0%b0%d0%b2%d0%b8%d1%81%d0%b8%d1%82%20%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d0%bd%d0%bd%d0%b0%d1%8f,%20%d1%82%d0%b0%d0%ba%d0%b6%d0%b5%20%d0%b1%d1%83%d0%b4%d1%83%d1%82%20%d0%b0%d0%b2%d1%82%d0%be%d0%bc%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%20%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d1%8b%20%d0%b2%20%d0%b1%d0%b0%d0%b7%d1%83%20%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85.%20%d0%95%d1%81%d0%bb%d0%b8%20%d0%be%d0%bd%d0%b8%20%d1%83%d0%b6%d0%b5%20%d0%bf%d1%80%d0%b8%d1%81%d1%83%d1%82%d1%81%d1%82%d0%b2%d1%83%d1%8e%d1%82%20%d0%b2%20%d0%b1%d0%b0%d0%b7%d0%b5,%20%d1%82%d0%be%20%d1%83%20%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d1%8f%d1%8e%d1%89%d0%b5%d0%b3%d0%be%20%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d1%8e%20%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d1%82%d0%b5%d0%bb%d1%8f%20%d0%b4%d0%be%d0%bb%d0%b6%d0%bd%d1%8b%20%d0%b1%d1%8b%d1%82%d1%8c%20%d0%bf%d1%80%d0%b0%d0%b2%d0%b0%20REFERENCES%20%d0%b4%d0%bb%d1%8f%20%d0%bd%d0%b8%d1%85.%20%d0%95%d1%81%d0%bb%d0%b8%20%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b8%20%d0%bd%d0%b5%20%d0%bd%d0%b0%d0%b9%d0%b4%d0%b5%d0%bd%d1%8b%20%d0%bd%d0%b8%20%d0%b2%20%d0%b1%d0%b0%d0%b7%d0%b5,%20%d0%bd%d0%b8%20%d0%b2%20%d1%82%d0%be%d0%bc%20%d0%b6%d0%b5%20%d0%ba%d0%b0%d1%82%d0%b0%d0%bb%d0%be%d0%b3%d0%b5,%20%d0%b3%d0%b4%d0%b5%20%d0%b8%20%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d0%b0%d1%8f,%20%d0%b8%d0%bb%d0%b8%20%d0%bd%d0%b0%20%d0%bd%d0%b8%d1%85%20%d0%bd%d0%b5%d1%82%20%d1%81%d0%be%d0%be%d1%82%d0%b2%d0%b5%d1%82%d1%81%d1%82%d1%83%d1%8e%d1%89%d0%b8%d1%85%20%d0%bf%d1%80%d0%b0%d0%b2,%20%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%20%d0%bd%d0%b5%20%d0%b1%d1%83%d0%b4%d0%b5%d1%82%20%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd.assembly_bits%d0%91%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%b5%20%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5%20%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b8.%20%d0%95%d1%81%d0%bb%d0%b8%20%d1%81%d0%b1%d0%be%d1%80%d0%be%d0%ba%20%d0%bd%d0%b5%d1%81%d0%ba%d0%be%d0%bb%d1%8c%d0%ba%d0%be,%20%d1%82%d0%be%20%d0%bf%d0%b5%d1%80%d0%b2%d0%be%d0%b9%20%d0%b4%d0%be%d0%bb%d0%b6%d0%bd%d0%b0%20%d0%b8%d0%b4%d1%82%d0%b8%20%d0%b3%d0%bb%d0%b0%d0%b2%d0%bd%d0%b0%d1%8f%20%d0%b8%d0%b7%20%d0%bd%d0%b8%d1%85,%20%d0%b0%20%d0%bf%d0%be%d1%82%d0%be%d0%bc%20%d1%82%d0%b5,%20%d0%be%d1%82%20%d0%ba%d0%be%d1%82%d0%be%d1%80%d1%8b%d1%85%20%d0%be%d0%bd%d0%b0%20%d0%b7%d0%b0%d0%b2%d0%b8%d1%81%d0%b8%d1%82.%20%d0%a2%d0%b0%d0%ba%d0%b0%d1%8f%20%d1%82%d0%b5%d1%85%d0%bd%d0%be%d0%bb%d0%be%d0%b3%d0%b8%d1%8f%20%d0%bf%d0%be%d0%b7%d0%b2%d0%be%d0%bb%d1%8f%d0%b5%d1%82%20%d0%bc%d0%b8%d0%bd%d0%be%d0%b2%d0%b0%d1%82%d1%8c%20%d1%84%d0%b0%d0%b7%d1%83%20%d0%b7%d0%b0%d0%bf%d0%b8%d1%81%d0%b8%20%d0%bd%d0%b0%20%d0%b4%d0%b8%d1%81%d0%ba%20%d0%bf%d1%80%d0%b8%20%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b9%20%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d0%b8%20%d0%ba%d0%be%d0%b4%d0%b0%20%d0%b8%20%d0%b8%d0%b7%d0%b1%d0%b5%d0%b6%d0%b0%d1%82%d1%8c%20%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%20%d1%81%20%d0%b4%d0%be%d1%81%d1%82%d1%83%d0%bf%d0%be%d0%bc%20%d0%ba%20%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%be%d0%b9%20%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b5.%20%d0%98%d0%bc%d0%b5%d0%bd%d0%bd%d0%be%20%d1%82%d0%b0%d0%ba%d0%b8%d0%bc%20%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%bc%20%d0%bf%d1%80%d0%be%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%b8%d1%82%20%d1%80%d0%b0%d0%b7%d0%b2%d0%b5%d1%80%d1%82%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5%20%d1%81%d0%b1%d0%be%d1%80%d0%be%d0%ba%20%d0%b8%d0%b7-%d0%bf%d0%be%d0%b4%20MS%20Visual%20Studio%208.0%20(Whidbey).PERMISSION_SET%20{SAFE%20|%20EXTERNAL_ACCESS%20|%20UNSAFE%20}%d0%a3%d1%80%d0%be%d0%b2%d0%b5%d0%bd%d1%8c%20%d0%bf%d1%80%d0%b0%d0%b2,%20%d0%ba%d0%be%d1%82%d0%be%d1%80%d1%8b%d0%b5%20MS%20SQL%20Server%20%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%b8%d1%82%20%d0%ba%d0%be%d0%b4%d1%83%20%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b8%20%d0%bf%d1%80%d0%b8%20%d0%b5%d0%b3%d0%be%20%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d0%b8.%20%d0%9f%d0%be%20%d1%83%d0%bc%d0%be%d0%bb%d1%87%d0%b0%d0%bd%d0%b8%d1%8e%20%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d1%82%d1%81%d1%8f%20SAFE.SAFE%20>Имя параметраОписаниеassembly_nameИмя сборки .NET (assembly). Оно должно быть уникальным в пределах текущей базы данных, удовлетворять требованиям MS SQL Server, предъявляемых

MS SQL Server 9 “Yukon”. Интеграция с .NET

Информация

Компьютеры, программирование

Другие материалы по предмету

Компьютеры, программирование

Сдать работу со 100% гаранией
/p>

public bool IsNull

{

get

{

return _isNull;

}

}

#endregion

}В первую очередь обратим внимание на атрибут SqlUserDefinedAggregate, который предваряет описание нашего класса. В нем определено несколько параметров (таблица 5).

Имя параметраОписаниеFormatФормат сериализации объектов этого класса. Подробности в следующем разделе.MaxByteSizeМаксимальный размер сериализованного объекта. Подробности в следующем разделе.IsInvariantToDuplicatesЗависит ли агрегированное значение от наличия дубликатов во входных данных (по умолчанию да). Например, для функции MIN() совершенно неважно, сколько раз повторяются входные значения, а для функции SUM() важно. Оптимизатор запросов SQL Server может использовать эту информацию для минимизации количества вызовов метода Accumulate.IsInvariantToNullsВлияет ли наличие NULL-значений во входных данных на агрегированное значение. Для большинства встроенных агрегирующих функций (кроме COUNT()) это так.IsNullIfEmptyОзначает, что агрегирующая функция возвращает NULL для пустых входных наборов. Например, функция MIN при выполнении на пустом наборе возвращает как раз NULL , а функция COUNT() 0. IsInvariantToOrderДанный параметр пока не документирован; судя по названию, он должен определять, влияет ли на результат порядок подачи значений в метод Accumulate(). См. примечание после таблицыТаблица 5.

ПРЕДУПРЕЖДЕНИЕ

Все встроенные агрегирующие функции (а также наш пример) являются коммутативными, что позволяет серверу выбирать порядок сканирования входных данных по своему усмотрению. Однако, например, результат функций типа First() или Last(), (которые должны возвращать соответственно первое или последнее значение в наборе), очевидным образом зависит от порядка входных значений. Тем не менее, пока непонятно, как можно использовать подобные функции дело в том, что синтаксис SQL не позволяет определять порядок агрегирования записей. Оператор ORDER BY применим только к выходному набору записей, и использовать в нем можно только те поля, по которым выполняется группировка. В обычных вложенных запросах (по результатам которых можно строить запросы с группировкой) применение ORDER BY запрещено. Скорее всего (это только мое предположение!) разработчики MS SQL Server Yukon предполагают использовать свойство SqlUserDefinedAggregateAttribute.IsInvariantToOrder для тех случаев, когда программист каким-либо способом все же может гарантировать определенное упорядочивание входных данных это свойство должно убедить сервер воздержаться от переупорядочивания записей перед агрегированием. Пока что мне не удалось обнаружить какого-либо влияния этого свойства на поведение сервера.Для того, чтобы наш объект мог принимать значение NULL, необходимо реализовать интерфейс INullable. Этот интерфейс определяет единственное read-only свойство bool IsNull. Все классы из System.Data.SqlTypes реализуют этот интерфейс. В нашем примере объект принимает значение NULL при инициализации, и перестает быть Null сразу, как только ему будет передано не-NULL значение в метод Accumulate или Merge.

Пользовательские типы данных

Систему типов SQL Server можно расширить с помощью пользовательских типов данных (User-defined Types, UDT). Пользовательские типы реализуются как управляемый класс на любом из CLR-языков и регистрируются в SQL Server. Такой тип можно использовать для определения типа колонки в таблице, или как переменную (параметр процедуры) в выражении Т-SQL. При этом методы объектов можно вызывать прямо из T-SQL.

Создание пользовательского типа данных

В T-SQL пользовательский тип данных регистрируется при помощи оператора CREATE TYPE:

CREATE TYPE [ type_schema_name. ] type_name

{ [ FROM base_type [ ( precision [ , scale ] ) | ( 'urn:schema-namespace' ) ]

[ NULL | NOT NULL ] ]

| [ EXTERNAL NAME [ assembly_schema_name. ] assembly_name [ :class_name ] ]

}В операторе указывается имя класса из предварительно загруженной в базу сборки.

Альтернативой прямому использованию T-SQL, как и в других случаях, служит автоматическое развертывание проектов MS Visual Studio .Net Whidbey. Классы, помеченные атрибутом SqlUserDefinedType (мы подробно рассмотрим его чуть позже при обсуждении сериализации) автоматически регистрируются в качестве пользовательских типов при развертывании проектов типа SQL Server Project.

Для того, чтобы класс .NET можно было использовать в качестве пользовательского типа данных SQL Server, он должен выполнять некоторые обязанности:

Иметь конструктор без параметров. Как правило, он возвращает экземпляр, соответствующий значению NULL (об этом далее).

Поддерживать NULL-значения. Класс должен реализовывать интерфейс INullable, который описан в предыдущем разделе. Также необходима реализация в классе статического свойства Null, которое возвращает NULL-объект этого класса, т.е. должно быть MyClass.Null.IsNull == true. Все методы должны корректно обрабатывать передачу в параметрах как экземпляра Null, так и значения null.

Поддерживать конверсию в строку и обратно: в классе должен быть определен метод Parse(SqlString s) и должным образом перекрыт метод ToString().

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

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

В качестве упражнения я реализовал тип «точка на плоскости». Он умеет представлять свои координаты как в декартовых, так и в полярных координатах.

using System;

using System.Data.Sql;

using System.Data.SqlTypes;

using System.Text.RegularExpressions;

using System.Runtime.InteropServices;

 

[Serializable]

[SqlUserDefinedType(Format.Native)]

[StructLayout(LayoutKind.Sequential)]

public class SqlPoint: INullable

{

#region NULLability

private bool _isNull = true;

public bool IsNull

{

get

{

return _isNull;

}

}

public static SqlPoint Null

{

get

{

return new SqlPoint();

}

}

#endregion

#region Конверсия в строку и обратно

public override string ToString()

{

return IsNull? "null" : String.Format("X: {0}; Y: {1}", x, y);

}

public static SqlPoint Parse(SqlString s)

{ // Я не очень хорошо владею регулярными выражениями,

// тем не менее, этот метод в состоянии преобразовать

// результат вызова метода ToString обратно в SqlPoint.

if (s.IsNull || s.Value.ToLower() == "null")

return Null;

SqlPoint p = new SqlPoint();

Regex t = new Regex(@"x:(?<x>\d*(\.\d+)?)\s*\W*y:(?<y>\d*(\.\d+)?)",

RegexOptions.IgnoreCase);

Match match = t.Match(s.Value);

p.x = SqlDouble.Parse(match.Groups["x"].Value);

p.y = SqlDouble.Parse(match.Groups["y"].Value);

return p;

}

#endregion

#region Наши данные

private double _x=0;

private double _y=0;

public SqlDouble x

{

get

{

return IsNull ? SqlDouble.Null : new SqlDouble(_x);

}

set

{

if (!value.IsNull)

{

_x = value.Value;

_isNull = false;

}

}

}

public SqlDouble y

{

get { return IsNull? SqlDouble.Null: new SqlDouble(_y); }

set

{

if (!value.IsNull)

{

_y = value.Value;

_isNull = false;

}

}

}

public SqlDouble R // А эти свойства мы будем вычислять.

{

get

{

return IsNull

? SqlDouble.Null

: new SqlDouble(System.Math.Sqrt(_y*_y +_x*_x));

}

set

{

if (value.IsNull)

{

_isNull = true;

return;

}

 

double alpha = Alpha.IsNull? 0 : Alpha.Value;

_x = System.Math.Cos(alpha) * value.Value;

_y = System.Math.Sin(alpha) * value.Value;

}

}

public SqlDouble Alpha

{

get

{

return (IsNull)

? SqlDouble.Null

: new SqlDouble(System.Math.Atan2(_y, _x));

}

set

{

if (value.IsNull)

{

_isNull = true;

return;

}

 

double r = R.IsNull ? 0 : R.Value;

 

_x = System.Math.Cos(value.Value) * r;

_y = System.Math.Sin(value.Value) * r;

}

}

#endregion

}После регистрации данного класса как пользовательского типа выполнение вот таких запросов:

declare @p SqlPoint

set @p::x = 3

set @p::y = 4

select @p::x, @p::y, @p::R, @p::ToString()

set @p::R = 10

select @p::x, @p::y, @p::R, @p::ToString()

set @p::Alpha = 0

select @p::x, @p::y, @p::R,

Похожие работы

<< < 1 2 3 4 5 6 7 8 > >>