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% гаранией
апример, списка получателей e-mail. Сортировка по обращенному адресу поставит рядом адреса в одном домене, и можно будет оптимизировать рассылку писем.Возвращаем ISqlReader

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

[SqlFunc(TableDefinition = "D datetime, course decimal(10, 4)")]

[SqlFunction(DataAccess = DataAccessKind.Read,

SystemDataAccess = SystemDataAccessKind.None,

IsDeterministic = false, IsPrecise = true)]

public static ISqlReader GetCourseChanges(DateTime start, DateTime end)

{

SqlCommand cmd = SqlContext.GetCommand();

cmd.CommandText = @"

select changeDate, course from Course

where changeDate between @start and @end";

cmd.Parameters.AddWithValue("@start", start);

cmd.Parameters.AddWithValue("@end", end);

return cmd.ExecuteReader();

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

Увы, пока что мне не удалось заставить этот пример работать. Сервер неуклонно возвращает ошибку «Reader is closed». Каким образом избежать закрытия Reader после возвращения его серверу, я пока не понял.Работаем с SqlResultSet

Для тех случаев, когда необходимо сформировать возвращаемый набор данных вручную, предусмотрен доступ к нему через метод контекста SqlContext.GetReturnResultSet(). Объект, возвращаемый этим методом, уже проинициализирован в соответствии с декларированной структурой функции. В него нужно добавить требуемые записи. В принципе, можно как добавлять, так и удалять/изменять записи, если это кажется необходимым. Воспроизведем поведение хранимой процедуры CurrencyCourse, созданной в конце предыдущего раздела:

[SqlFunc(TableDefinition = "D datetime, course decimal(10, 4) NULL")]

[SqlFunction(DataAccess = DataAccessKind.Read,

SystemDataAccess = SystemDataAccessKind.None,

IsDeterministic = false, IsPrecise = true)]

public static void GetCourseTable(DateTime start, DateTime end)

{

using (SqlCommand cmd = SqlContext.GetCommand())

{

cmd.CommandText = @"

select changeDate, course from Course

where changeDate between @start and @end";

cmd.Parameters.AddWithValue("@start", start);

cmd.Parameters.AddWithValue("@end", end);

DateTime current = start;

SqlDecimal course = SqlDecimal.Null;

SqlResultSet source = cmd.ExecuteResultSet(ResultSetOptions.None);

SqlResultSet dest = SqlContext.GetReturnResultSet();

SqlDataRecord rec;

while (source.Read())

{

while (current < source.GetDateTime(0))

{

rec = dest.CreateRecord();

rec.SetSqlDecimal(1, course);

rec.SetDateTime(0, current);

dest.Insert(rec);

current = current.AddDays(1);

}

course = source.GetDecimal(1);

}

while (current <= end)

{

rec = dest.CreateRecord();

rec.SetDateTime(0, current);

rec.SetSqlDecimal(1, course);

dest.Insert(rec);

current = current.AddDays(1);

}

}

}Обратите внимание, что теперь в атрибуте SqlFunction содержится значение свойства DataAccess = DataAccessKind.Read, указывая на то, что функция читает данные из базы.

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

Обратите внимание также на то, что на этот раз для доступа к данным мы используем SqlResultSet вместо SqlDataReader. Дело в том, что одновременно читать из базы и работать с возвращаемым набором записей нельзя возникает исключение с сообщением о том, что данное соединение уже используется. Возможно, данная особенность поведения будет изменена при выпуске финальной версии. Но пока единственным способом написать подобную функцию является чтение данных целиком до начала формирования выходного набора данных.Агрегирующие функции

Большинству разработчиков для построения своих приложений вполне хватает стандартного набора агрегирующих функций. Однако теперь настал праздник и для редких любителей сделать что-то необычное в новом MS SQL Server можно реализовать свой способ выйти за пределы SUM, AVG и СOUNT.

Создаются они при помощи оператора CREATE AGGREGATE:

CREATE AGGREGATE [ schema_name. ] aggregate_name

( @param_name < input_sqltype > )

RETURNS < return_sqltype >

EXTERNAL NAME assembly_name [ :class_name ]

 

< input_sqltype > ::=

system_scalar_type | { [ udt_schema_name. ] udt_type_name }

< return_sqltype > ::=

system_scalar_type | { [ udt_schema_name. ] udt_type_name }На этот раз написания одного метода недостаточно. Вместо этого для подсчета агрегатов используются объекты. Идея проста по мере просмотра исходных данных мы накапливаем то, что нужно накапливать, а зетем выводим накопленное в выходной набор. Соответственно для каждого из этих действий нужно реализовать по методу:

Имя методаОписаниеpublic void Init()public void Init(input_type value)Инициализирует объект. Вызывается один раз на группу агрегируемых значений. Если реализована версия метода с одним параметром, то SQL Server может использовать ее для передачи первого значения в группе. Тип параметра value (input_type) должен быть совместимым с тем типом, который указан как input_sqltype в операторе CREATE AGGREGATE.public void Accumulate(input_type value)После инициализации объекта, сервер вызывает этот метод по одному разу для каждого агрегируемого значения. (На список подаваемых на вход значений, помимо состава полей в операторе GROUP BY, оказывает влияние также и наличие ключевого слова distinct перед агрегируемым выражением. Как и для встроенных функций, это ключевое слово приведет к тому, что в список для каждой группы попадут только различные значения агрегируемого выражения). Тип параметра value должен быть совместимым с тем типом, который указан как input_sqltype в операторе CREATE AGGREGATE.public return_type Terminate()Несмотря на страшное название, этот метод всего лишь должен вернуть то самое агрегированное значение, которое было вычислено для группы входных значений. Тип результата должен быть совместимым с тем типом, который указан как return_sqltype в операторе CREATE AGGREGATE.public void Merge(udagg_type group)Этот метод предназначен для случаев, когда SQL Server создает больше одного агрегирующего объекта на одну группу входных значений. Например, при выполнении запроса на многопроцессорной машине, входные данные могут быть разделены на несколько потоков для одновременной обработки. Перед выводом данных необходимо выполнить слияние рассчитанных агрегатных значений. Именно это и делает этот метод. Он принимает единственный параметр того же класса, в котором объявлен.Таблица 4.

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

Тем, кто плохо помнит школьный курс, напомню, что среднее геометрическое из N чисел это корень N-ной степени из их произведения. (А среднее арифметическое N чисел, которое обычно и подразумевается под термином «среднее значение» - это сумма этих чисел, деленная на N).

ПРИМЕЧАНИЕ

К сожалению, расчет среднего геометрического по определению очень быстро приводит к переполнению даже на очень небольших наборах входных данных произведение растет слишком быстро. Поэтому мы схитрим и воспользуемся тем математическим фактом, что произведение N чисел равно экспоненте от суммы их логарифмов. Вместо извлечения корня степени N (а это то же самое, что и возведение в степень 1/N) мы поделим на N сумму логарифмов перед применением функции Exp().

[Serializable]

[SqlUserDefinedAggregate(Format.Native, IsInvariantToDuplicates = false, IsInvariantToNulls = true, IsInvariantToOrder = true, IsNullIfEmpty = true)]

[StructLayout(LayoutKind.Sequential)]

public class AvgGeom: INullable

{

private double _agg;

private int _count;

private bool _isNull = true;

 

#region User-Defined Attribute Required Methods

public void Init()

{

_agg = 0;

_count = 0;

_isNull = true;

}

public void Accumulate(SqlDouble Value)

{

if (!Value.IsNull)

{

_agg += System.Math.Log(Value.Value);

_count++;

_isNull = false;

}

}

public void Merge(AvgGeom Group)

{

if (!Group.IsNull)

{

_agg += Group._agg;

_count += Group._count;

_isNull = false;

}

}

public SqlDouble Terminate()

{

if (IsNull)

return SqlDouble.Null;

else

return new SqlDouble(System.Math.Exp(_agg / _count));

}

#endregion

 

#region INullable Members<

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

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