Главная » Microsoft SQL Server, Базы данных » Расширяемость с помощью уровня абстракции данных

0

18            -j уществует довольно распространенная ситуация: схема базы данных проектировалась много лет или даже десятилетий назад, и несмотря на то, что все в организации хотят улучшить ее структуру, это настолько рискованно и влечет за собой такие затраты, что никто за это не берется. А причина одна — существует слишком много непосредственных подключений к таблицам данных. Самые большие затраты влечет за собой не создание, а поддержка программного обеспечения. Что же касается баз данных, то прямые подключения в динамических запросах SQL к таблицам поддерживать труднее всего. Как в принципе домино: любое изменение в схеме отражается на сбоях в программах, отчетах и пакетах DTS. Обычная инструкция SELECT практически берет в заложники базу данных, и любая надежда на расширение рассеивается, как дым. Главное достоинство SQL— простота создания запросов к данным — становится его слабым звеном. Ответ лежит в уровнях абстракции.

Уровни абстракции окружают нас повсюду. Любой интерфейс пользователя, скрывающий за своей простотой всю сложность обработки данных, представляет собой уровень абстракции. Хорошим примером уровня абстракции, с которым нам приходится сталкиваться ежедневно, являются стандартные элементы управления автомобилем. Привычный руль позволяет нам управлять машиной, не задумываясь о том, как он соединен с передними колесами. Педаль тормоза позволяет замедлить движение автомобиля, совершенно не вдаваясь в тонкости функционирования тормозной системы. То же можно сказать и о педали газа, рычаге переключения передач, фарах и т.д. Привычные элементы управления являются уровнем абстракции механической работы автомобиля.

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

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

Принципы информационной архитектуры, сформулированные в главе 1. поддерживают концепцию уровней абстракции данных. Главный принцип гласит, что данные должны быть доступны как в настоящий момент, так и в будущем. Если база данных должна выжить в будущем (а многие базы намного переживают свои исходные интерфейсы пользователя), она должна быть расширяемой. А лучший способ гарантировать расширяемость — это использовать уровень абстракции данных.

Знатоки уже утомились доказывать, что архитектуры “клиент/сервер” и многоуровневая не справляются с работой и что единственный ответ лежит в использовании архитектуры, ориентированной на службы (SOA). Мне кажется, что это не совсем так. Базы данных, созданные без использования уровня абстракции данных, могут действительно не работать, как нужно. В то же время при использовании уровня абстракции данных будут отлично работать все виды архитектур: и многоуровневая, и “клиент/сервер”, и SO А.

Уровень абстракции данных может существовать как в базе данных (в виде хранимых процедур, представлений и функций), так и в приложении (с помощью использования .NET и ADO). В то же время не смешивайте эти два подхода.

Лично я предпочитаю создавать уровень абстракции в базе данных, и на это есть две причины. Во-первых, это позволяет расположить программный код проверки и все классификаторы настолько близко к данным, насколько это возможно. Во-вторых, это гарантирует, что никакой сторонний код не обойдет уровень абстракции и не получит прямой доступ к данным. Понимаю, что некоторые не согласны с этой точкой зрения, и в этом нет ничего плохого — главное, чтобы уровень абстракции существовал.

В целом уровню абстракции данных нужен отдельный интерфейс для каждой из следующих задач:

?               вставка данных;

?               обновление данных;

Ш.       удаление данных;

?               отбор отдельной строки и перечисление всех пользовательских объектов.

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

В этой главе мы рассмотрим ряд хранимых процедур из уровня абстракции данных учебной базы OBXKites.

Хранимая процедура AddNew

Хранимая процедура AddNew отвечает за вставку в базу данных новых строк. Главной задачей этой процедуры является проверка допустимости данных, преобразование кодов во

внешние ключи и выполнение инструкции INSERT. Процедура AddNew также способна решать вопросы ожидания блокировки. Ниже приведен полный код хранимой процедуры AddNew из базы данных OBXKites.

CREATE PROCEDURE pProduct_AddNew(

@ProductCategoryName NVARCHAR(50),

©Code CHAR(10),

@Name NVARCHAR(50),

@ProductDescription NVARCHAR(100) = NULL )

AS

SET NOCOUNT ON DECLARE

@ProductCategoryID UNIQUEIDENTIFIER SELECT @ProductCategoryID = ProductCategorylD FROM dbo.ProductCategory

WHERE ProductCategoryName = @ProductCategoryName IF @@Error <> 0 RETURN -100 IF ©ProductCategorylD IS NULL BEGIN

RAISERROR (‘Категория товаров: ”%s’! не найдена’,

15,1,@ProductCategoryName)

RETURN -100 END BEGIN TRY

INSERT dbo.Product (ProductCategorylD, Code, ProductName, ProductDescription)

VALUES (©ProductCategorylD, @Code, @Name,

©ProductDescription )

END TRY BEGIN CATCH

RAISERROR (‘Невозможно вставить новый товар’, 15,1)

RETURN -10 0 END CATCH

Для тестирования процедуры попытаемся вставить в таблицу Product товар с кодом 999:

ЕХЕС pProduct_AddNew

@ProductCategoryName = ‘ОВХ’,

@Code = ‘ 999′,

@Name = ‘Test Kit’,

©ProductDescription

= ‘official kite testing kit for contests.’

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

SELECT ProductName, ProductCategoryName FROM dbo.Product

JOIN ProductCategory

ON Product.ProductCategorylD

= ProductCategory. ProductCategorylD WHERE Code = ‘999’

Получим ожидаемый результат:

Name            ProductCategoryName

Test Kit        OBX

Хранимая процедура Fetch

Хранимая процедура Fetch извлекает данные. Если усложнить ее, то можно принимать множество параметров, возвращая, в зависимости от их состава, одну строку, их отфильтрованный набор или все множество строк. При этом совершенно не нужно писать для каждого конкретного набора данных отдельную процедуру. В предложении WHERE используется значение по умолчанию, null, так что если какой-либо параметр не предоставлен, соответствующий критерий отключается.

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

CREATE PROCEDURE pProduct_Fetch(

(©ProductCode CHAR (15) = NULL,

(©Productcategory CHAR (15) = NULL )

AS

SET NoCount ON

SELECT Code, ProductName, ProductDescription, ActiveDate, DiscontinueDate, ProductCategoryName, [RowVersion]

– Product.Created, Product.Modified FROM dbo.Product

JOIN dbo.Productcategory

ON Product.ProductCategorylD

= Productcategory.ProductCategorylD WHERE ( Product. Code = (©ProductCode OR (©ProductCode IS NULL )

AND ( Productcategory.ProductCategoryName = (©Productcategory OR (©Productcategory IS NULL )

IF (©(©Error <> 0 RETURN -10 0 RETURN

Вызовем эту процедуру безо всяких параметров и получим данные обо всех товарах:

ЕХЕС pProduct_Fetch

Представленные ниже результаты выполнения этой процедуры усечены по столбцам и строкам.

Code Name                       Modified

1001                                       Basic Box Kite 21 inch     2002-02-18 09:48:31.700

1002                                       Dragon Flight 2002-02-18 15:19:34.350

1003                                       Sky Dancer    2002-02-18 09:48:31.700

Если подставить параметр (©ProductCode, то хранимая процедура Fetch вернет информацию только об одном товаре (столбцы результата усечены):

ЕХЕС pProduct_Fetch (©ProductCode = ‘1005’

Вот ее результат:

Code Name                       Modified

1005 Eagle Wings                2002-02-18 09:48:31.700

Установка второго параметра позволяет получить список всех товаров указанной категории (в результате усечены строки и столбцы):

EXEC pProduct_Fetch

(©ProductCategory = ‘Book1

Результат таков:

Code Name                       Modified

1036  Adventures in the OuterBanks 2002-02-25 17:13:15.430

1037  Wright Brothers Kite Designs 2002-02-25 17:13:15.430

1038                                        The Lighthouses of the OBX 2002-02-25 17:13:15.430

1039                                        Outer Banks Map     2002-02-25 17:13:15.430

1040  Kiters Guide to the Outer Banks 2002-02-25 17:13:15.430

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

По теме:

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