Программирование >>  Программирование баз данных 

1 ... 165 166 167 [ 168 ] 169 170 171 ... 346


щиеся к текущему каталогу. В ходе циклической обработки происходит заполнение массива данными, полученными путем определения свойств FullName и LastWriteTime каждого очередного файла:

private static void GetFiles(string d, string sWildCard, ArrayList aPileArray)

foreach (string f in Directory.GetFiles(d, sWildCard))

Filelnfo fi = new Filelnfo(f);

object [] colunrn = new object [2]; colunm[0] = f i. FullName ; column[1] = fi.LastWriteTime;

aFileArray.Add(column);

Ha основании полученных данных мы можем приступить к окончательному решению поставленной задачи путем фактической реализации функции FillRow, назначение которой сводится к обеспечению связи между массивом и внешним миром; иными словами, эта функция обеспечивает построчную передачу данных.

private static void FillRow (Object ob j, out string filename, out DateTime date)

object [] row = (object []) obj ;

filename = (string)row[0]; date = (DateTime)row[1];

После завершения описанньгх подготовительных действий мы можем начать компиляцию и выгрузку сборки. Для этого используется та же команда CREATE ASSEMBLY, к которой мы обращались на протяжении всей главы, но с небольшим дополнением - необходимо объявить сборку как имеющую заданное право доступа EXTERNAL ACCESS. Чтобы у нас была возможность применять такое объявление, необходимо выполнить одно из двух условий, описанных ниже.

Сборка должна быть подписана с помощью сертификата, который соответствует пользователю с надлежащими правами EXTERNAL ACCESS (дополнительная информация по этой теме приведена в главе 22).

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

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

ALTER DATABASE AdventureWorks SET TRUSTWORTHY ON

После этого мы получаем возможность завершить выгрузку сборки с надлежащими правами дост)Т1а: USE AdventureWorks

CREATE ASSEMBLY fExampleTVF

FROM <solution path>\ExampleTVF\bin\Debug\ExampleTVF.dll WITH PERMISSION SET = EXTERNAL. ACCESS



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

CREATE FUNCTION fTVFExample (

©RootDir nvarchar(max), ©Wildcard nvarchar(max), ©IncludeSubDirs bit

RETURNS TABLE (

FileName nvarchar(max), LastWriteTime nvarchar(max)

AS EXTERNAL NAME ExampleTVF.UserDefinedFunctions. DirectoryList И с этого момента подготовка к проверке завершена:

SELECT FileName, LastWriteTime

FROM dbo.fTVFExample сел-, * . sys , 0)

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

FileName LastWriteTime

C:\CONFIG.SYS 2006-04-01 00:21:43.470

C:\I0.SYS 2006-04-01 00:21:43.470

C:\MSDOS.SYS 2006-04-01 00:21:43.470

C:\pagefile.sys 2006-05-02 20:08:56.500

(4 row(s) affected)

Итак, в этом разделе было показано не только то, как можно создать табличную функцию, но и как получить доступ к внешним данным, а это открывает перед разработчиками весьма значительные возможности!

Создание агрегирующих функций

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

Рассмотрим определение понятия агрегирующей ф\тнкции. Прежде всего отметим, что к категории агрегирующих функций относятся функции SUM, AVG, MIN и MAX. Эти функции обрабатывают определенный набор данных, а затем возвращают значение, полученное по результатам определеьшого анализа всего этого набора. Данные, полученные с помощью агрегирующей функции, могуг быть основаны на всем результирующем наборе или получены с учетом каких-то критериев, заданных в конструкции GROUP BY.



На практике при попытке выполнить анализ, требуемый для получения агрегированной информации, вскоре обнаруживается, что эта задача является довольно сложной. В отличие от других функций, в которых все действия могут быть реализованы в коде единственного вызова обрабатывающего кода, в агрегирующей функции приходится чередовать действия самой функции (то, что фактически сводится к агрегированию) с действиями, выполняемыми в СУБД SQL Server одновременно с этим (например, с организацией групп для конструкции GROUP BY). В связи с этим приходится применять своего рода поэтапные вызовы класса сборки. По этой причине предусмотрены четыр этапа вызова класса, и в каждом из этих вызовов допускается поддержка различных методов, как описано ниже.

Init. На этом этапе обеспечивается инициализация функции. Если речь идет об агрегирующей функции, то с помощью данного метода может быть создан своего рода накопитель или объявлена какая-то другая вспомогательная переменная; иными словами, метод Init позволяет инициализировать переменные, обеспечивающие накопление данных, и другие дополнительные переменные.

Accumulate. Этот метод вызывается в СУБД SQL Server по одному разу для каждой строки, обрабатываемой с помощью агрегирующей функции. Разработчику дано полное право использовать функцию в соответствии с собственным замыслом, но предполагается, что метод Accumulate будет служить для реализации той логики накопления данных, которая должна лечь в основу агрегирующей функции.

Merge. СУБД SQL Server - это многопотоковое приложение, и в нем вполне допускается использование многочисленных потоков, в каждом из которых может вызываться одна и та же конкретная функция. Как таковой метод Merge может применяться для объединения результатов, полученных с помощью различных потоков, в один окончательный результат. В зависимости от типа создаваемой агрегирующей функции решение задачи объединения данных может оказаться довольно сложным. Тем не менее допускается возможность использования в классе закрытых методов класса, что позволяет контролировать количество работающих потоков и учитывать вклад, внесенный каждым потоком. Следует отметить, что разрабатываемая агрегирующая функция получает в качестве параметра копию класса (при использовании метода Merge можно рассматривать такую организацию вызова функции как аналог рекурсивного вызова), а не накапливаемое значение какого-либо другого типа; это предусмотрено для того, чтобы предусмотреть возможность получения в агрегирующей функции надлежащих результатов, вычисленных другим потоком.

Terminate. Метод Terminate противоположен методу Init. Именно вызов этого метода приводит к фактическому получению результата.

Теперь рассмотрим применение описанных методов на практике.

Для этого необходимо прежде всего создать новый проект в программе Visual Studio (в рассматриваемом примере автор назвал проект Example Aggregate), а затем добавить к нещ новую агрегирующую функцию (щелкните правой кнопкой мыши на проекте в разрабатываемом решении и выберите Add Aggregate). После этого в СУБД SQL Server создается стандартный шаблон, который включает все четыре метода, описанных выше:



1 ... 165 166 167 [ 168 ] 169 170 171 ... 346

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика