Об’єкти доступу до даних

Всі приклади програмного коду, наведені у цій главі, були створені на основі VBNET 2005 Їх можна знайти на сайті книги

У шаблоні доступу до даних DAO спадкування і поліморфізм використовуються для побудови ієрархії обєктів даних Загальна модель продемонстрована на рис 541

Рис 541 У цьому прикладі моделі DAO показано, як управляється окрема реалізація і як клієнт може посилатися на кожну з них

I В обєктно-орієнтованої середовищі поліморфізмом називають здатність

На замітку класів реалізовувати однаковий загальний інтерфейс На практиці це – ^ значить, що два або більше класу представляють загальний інтерфейс, який в клієнтському програмному коді може трактуватися як однотипний

Модель DAO для забезпечення функціональності низлежащих класів покладаючись-На замітку ється на технології успадкування У цій моделі завжди існують базові абстрактні класи, специфічні для обєктів кожного типу даних, які повинен підтримувати розробник Спеціалізований клас створюється для кожного обєкта доступу до бази даних, який необхідно підтримувати, і містить весь необхідний код SQL для своєї бази даних Зазвичай імя класу містить у собі імя бази даних, наприклад AddressSQLDAO або AddressAccessDAO Будь програмний код, який забезпечує використання цих обєктів, повинен спочатку знати, який тип DAO створювати

Як працюють сценарії DAO

Розглянемо один із сценаріїв DAO Основне завдання полягають в тому, щоб підтримувалися бази даних Microsoft SQL Server 2005 і Microsoft Access Визначення типу обєктів даних, який повинен підтримуватися, грунтується на зовнішньому прапорі, що міститься у файлі конфігурації

Базовий клас DAO Address, наведений в наступному фрагменті програмного коду, забезпечує функціональність всіх нащадків, що підтримують конкретну базу даних Різні властивості членів будуть загальними Єдиним фактичним відмінністю є спосіб завантаження даних з джерела

Базовий клас DAO Address

Public Mustlnherit Class Address

1 Визначено різні закриті змінні-члени,

1 такі як City, State, Streetl, Street2, і їх загальні члени

1,&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp 1 У кожному класі-спадкоємця буде реалізований метод Load 111 для унікального джерела даних, до якого здійснюється доступ

I I I_____________________________________

Public MustOverride Sub Load(ByVal strld As String)

End Class

Ключове слово MustOveride вимагає, щоб у кожному класі-спадкоємця був реалізований власний метод Load У прикладі, наведеному нижче, продемонстрований клас, який є спадкоємцем базового класу Address

AddressSQLDAOvb

Public Class SqlAddressDAO Inherits Address Визначення значення ключа файлу конфігурації

Private Const SQL_BINDING_INFO As String = &quotSql_BindingInfo&quot

‘Змінні класу успадковані від базового класу Address

I I I__________________________________________________

11 Заміщення методу Load, визначеного в класі Address

I I I__________________________________________________

Public Overrides Sub Load(ByVal strld As String)

Dim cmd As SqlCommand = Nothing

Dim conn As SqlConnection = Nothing Dim dr As SqlDataReader = Nothing Try

‘Визначення підключення до бази даних

conn = New SqlConnection(PropertyLoaderInstance _

.GetProperty(SQL_BINDING_INFO)) connOpen()

‘Налагодження та виконання команди SQL

cmd = New SqlCommand(PropertyLoaderInstance GetProperty ([2] Sql_Address_Select&quot ) Replace ( &quot %1&quot , strld) , conn) dr = cmdExecuteReader(CommandBehaviorCloseConnection)

If drRead Then 1 Завантаження змінних-членів читання

End If

Catch ex As Exception Приклад обробки помилок

Throw (ex)

Finally 1 Закриття змінних

If cmd IsNot Nothing Then cmdDispose()

If conn IsNot Nothing Then connClose()

If dr IsNot Nothing Then drClose()

End Try End Sub End Class

У версії VBNET 2005 було введено ключове слово IsNot, що реалізує більш зрозумілу форму умовних логічних перевірок Функціонально це ключове слово ідентично попередньому синтаксису-Not <змінна> Is <значення>

Обєкти даних, коли це можливо, здійснюють доступ до баз даних за допомогою збережених процедур Це забезпечує найкращу ізоляцію від змін реалізації бази даних В крайньому випадку обрамлялися інструкції SQL і в міру необхідності параметрізуется їх

Практичні поради щодо абстрагування доступу до бази даних у програмному коді см в главі 25

Коли змінні-члени визначені в абстрактному батьківському класі Address, клас AddressSQLDAO повинен ініціалізувати тільки власні змінні-члени Клас AddressAccessDAO забезпечує ту ж функціональність, але містить специфічний для програми Microsoft Access код підключення та інструкції SQL

У прикладі, наведеному нижче, продемонстрований клієнтський програмний код, що використовує класи AddressSqlDAO і AddressAccessDAO для збору інформації з джерел даних SQL Server і Access

TestMainvb

Public Class TestMain i i i____________________________

Sub Main()

Try

‘Локальна змінна, що зберігає посилання на загальний адресу

Dim objAddr As Address 1 Отримання даних з бази даних SQL Server і їх відображення objAddr = New SqlAddressDAO obj AddrLoad (2)

Call PrintAddress( objAddr )

1 Отримання даних з бази даних Access і їх відображення objAddr = New AccessAddressDAO obj AddrLoad (1)

Call PrintAddress( objAddr )

Catch ex As Exception ConsoleWriteLine(exMessage)

End Try End Sub

1 Виведення інформації про адресу

I I I______________________________________________

Private Sub PrintAddress( ByVal objAddr As Address )

ConsoleWriteLine(objAddrStreetl)

ConsoleWriteLine(objAddrCity)

‘Решта атрибути виводяться аналогічним чином

End Sub End Class

Подивившись на фактичне використання обєктів DAO, стає абсолютно очевидним, що доступ до даних SQL Server і Access реалізований одноманітно, оскільки управляється одним і тим же класом – Address У той час як поліморфізм є гарантом доступу клієнта до обєктів даних SQL Server і Access, зберігається необхідність знати, з яким конкретно джерелом даних ведеться робота Як було продемонстровано в програмному коді Test Main, відповідні обєкти даних створювалися явним чином, і ця залежність могла викликати проблеми у разі подцержку іншої бази даних або внесення змін в існуючу

Концепція DAO досить проста У реалізації і підтримці проекту не потрібні які-небудь спеціалізовані знання Ця концепція найбільше підходить для невеликої групи обєктів і джерел даних, і її можна реалізувати в програмному коді досить швидко

Переваги моделі DAO

Клієнт повинен визначити, який джерело даних використовувати Це досить тісно повязує клієнта з рівнем доступу до даних Одним з підходів до вирішення цієї проблеми є забезпечення відповідних методів батьківськими обєктами, і їх успадкування нащадками Однак слід зауважити, що це далеко не кращий спосіб абстрагування логіки джерела даних

Public Mustlnherit Class Address

I i i___________________________________________________________

1,&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp 1 У цьому класі реалізується та ж функціональність,

1Що і в класі Address, описаному вище,

1 однак доданий метод Getlnstance (),

” Визначає джерело даних

I I I___________________________________________________________

Public Shared Function Getlnstance() As Address If PropertyLoaderInstanceGetProperty(&quotUseSql&quot) _

Equals(&quotTrue&quot) Then

Return New AddressSqlDAO Else

Return New AddressAccessDAO End If

End Function

‘Вся інша функціональність описана вище

End Class

У той час як описана схема працездатна, всі помилки проектування тепер перенесені на рівень даних Ще одна проблема полягає в тому, що батьківський клас тепер повинен явно знати про всі своїх нащадках Ще один недолік повязаний з підтримкою Якщо умовна логіка повинна бути змінена, то слід оновлювати кожен окремий батьківський обєкт даних, який реалізує рішення Також слід оновлювати всі батьківські обєкти даних, якщо підтримувана база даних розширюється або додаються будь-які додаткові обєкти даних Таким чином, виходячи з вищесказаного, краще намагатися уникати використання цього підходу

Виникає питання, як ізолювати клієнта від вирішення цих питань Модель фабрики дозволяє винести бізнес-логіку Get Instance () в окремий клас і приховати відмінності баз даних від клієнтського програмного коду

Фабрики

Приклади програмного коду, описувані в цьому розділі, створені на мові VBNET 2005 їх можна знайти на сайті книги на сторінці f iles htm

Фабрика є централізованою точкою створення обєктів Коли клієнтський програмний код потребує обєктах даних, він виконує запит до фабрики, яка реалізує їх створення і ініціалізацію До того ж фабрика може містити бізнес-логіку, визначальну, які саме типи обєктів слід створити У прикладі, показаному на рис 542, ця логіка визначає, яка база даних використовується: SQL Server або Access

Фабрики представляють собою досить просту конструкцію, ізолюючу На замітку процес створення екземплярів класу від клієнтського додатку Фабрики можуть також виступати в якості проміжного рівня доступу до інших фабрикам На рис 542 обидва способи доступу до даних були реалізовані за допомогою первинної фабрики-DataObjectFactory Саме в ній реалізована бізнес-логіка визначення конкретної бази даних і передача запитів на створення обєктів до відповідної фабриці баз даних

У даному випадку модель фабрики допомогла відділити бізнес-логіку від обєктів доступу до даних і надала клієнтського програмного коду можливість формування єдиного підходу до створення нових обєктів даних Перевага цього підходу полягає в тому, що при зміні логіки джерела даних вся модифікація виконується в одному місці, а не в кожному базовому класі DAO Це спрощує підтримку і призводить програмний код у відповідність із загальними принципами обєктно-орієнтованого проектування

Створення класів DAO в специфічних для конкретних баз даних фабриках і використання їх як підлеглих фабрик дозволяє домогтися більшої інкапсуляції та однаковості До того ж це спрощує додавання нових баз даних – створюється відповідна нова підпорядкована фабрика і вносяться необхідні зміни в головну фабрику

Рис 542 У цьому прикладі фабрики продемонстровано взаємодію клієнтів і залежності фабрик

Представлений вище програмний код, що використовує клас Address, залишається придатним Фабрика просто консолідує відповідальність за створення обєктів даних в єдиному місці Це продемонстровано в наступному прикладі

Головна фабрика

Public Class DataObjectFactory

Inherits Factory i i i_____________________________________

111 Делегування запиту до обєкта підпорядкованої фабрики

I I I__________________________________________________

Public Shared Shadows Function GetDAO(ByVal typeRequested _

As FactorySupportedDAOs) As Object Try

If CBool( PropertyLoaderInstanceGetProperty(&quotUseSql&quot) ) Then Return SqlServerFactoryGetDAO(typeRequested)

Else

Return AccessFactory GetDAO (typeRequested)

End If Catch ex As Exception 1 Тут обробляється ситуація, коли прапор або значення 1UseSql недоступні Дане значення має визначатися 1 у файлі конфігурації програми

Throw New ApplicationException( &quotInvalid UseSql value&quot )

End Try End Function End Class

У наведеному вище фрагменті програмного коду головна фабрика визначає джерело даних і делегує запит спеціалізованої фабриці

Наступний фрагмент коду демонструє обробку цього делегування фабрикою Sql Server Factory Фактична робота виконується в пристосованій до конкретного джерела даних фабриці Фабрика Access виконує роботу аналогічним чином

Фабрика SqlServerFactory

Public Class SqlServerFactory Inherits Factory i i i__________________________________

1‘ Створення запитаного обєкта DAO

I i i____________________________________________________________

Public Shared Shadows Function GetDAO(ByVal typeRequested _

As FactorySupportedDAOs) As Object Select Case typeRequested

Case FactorySupportedDAOsAddress Return New AddressSqlDAO Case Else

Return Nothing End Select End Function End Class

Клас SqlServerFactory знає, які класи слід ініціалізувати, і не повинен турбуватися про інших джерелах даних Він самодостатній для обєктів SQL

У VBNET загальні методи не можуть заміщатися в підлеглих класах Для На замітку досягнення потрібного ефекту вони повинні оголошуватися з використанням клю-чевого слова Shadows

Тепер займемося питанням використання фабрик в програмному коді клієнтських додатків Розглянемо приклад

MainTestervb

Public Class MainTester i i i______________________________________________

11 Головний метод запрошувати обєкт даних у фабрики

1 1 1 Так як фабрика повертає тип даних Objects,

1 1 Тип значення повинен бути відповідним’1 чином перетворений

I 1 I___________________________________________________________

Sub Main()

Try

Dim objAddr As Address

objAddr = CType( SmarterDaoFactoryGetDAO( _

FactorySupportedDAOsAddress), Address) objAddrLoad(&quot1&quot)

Call PrintAddress(objAddr)

Catch ex As Exception ConsoleWriteLine(exMessage)

End Try End Sub

i i i____________________________________________________________

11 Виведення інформації про адресу

I I I___________________________________________________________

Private Sub PrintAddress( ByVal objAddr As Address )

ConsoleWriteLine(objAddrStreetl)

ConsoleWriteLine(objAddrCity)

‘Решта атрибути можна вивести тим же способом

End Sub End Class

Зверніть увагу на те, що створення специфічного для джерела даних обєкта в клієнтському коді було опущено – замість цього викликався метод Factory GetDAO (..) Цей метод містить логіку, визначальну, яка база даних повинна використовуватися, і спрямовуючу запит на створення обєкта відповідної підпорядкованої фабриці Це суттєвий крок у напрямку ізолювання клієнта від тонкощів створення джерела і обєкта даних

У наступному розділі ми обговоримо всі достоїнства і недоліки використання фабрик Після цього буде показано, як зробити доступ до даних в клієнтському програмному коді повністю прозорим

Переваги фабричної моделі

Як вже говорилося раніше, одним з переваг використання фабрик є централізація бізнес-логіки визначення джерела даних (клас SmarterDAOFactory) Головна фабрика обробляє запит за допомогою привязаних до конкретних джерел даних фабрик Таким чином, фабрика SmarterDAOFactory виступає в ролі посередника між клієнтським кодом і специфічними для баз даних фабриками Клієнт, завжди працюючий з одним і тим же джерелом даних, може направляти запит до специфічним фабрикам безпосередньо, в обхід головної фабрики Додаткові гідності укладені у спрощенні підтримки, полегшеної концептуалізації проекту, підвищенні легкості читання програмного коду До того ж розробники ще на етапі проектування знають, які обєкти підтримуються, оскільки функція середовища NET IntelliSense відображає списки значень обєктів фабрики Більше того, ця конструкція здатна працювати з великим числом обєктів і баз даних, ніж дозволяє DAO

Недоліки фабричної моделі

Всі недоліки, повязані з використанням фабричної моделі, стосуються реалізації Розглянутий у цій главі приклад дуже простий, і використання підлеглих фабрик насправді не було потрібно У той Водночас на практиці доводиться мати справу з великою кількістю обєктів і потенційних джерел даних, і використання підлеглих фабрик перетворюється на природну потребу В даному випадку використання головної фабрики в якості посередника вимагає додаткової координації роботи з підлеглими фабриками при додаванні нових баз і обєктів даних Всі підлеглі фабрики повинні програмуватися таким чином, щоб обслуговувати запити до невідомих джерел даних Ще одним недоліком є ​​те, що головна фабрика повинна надавати всі безліч доступних обєктів і це може викликати проблеми, якщо підлеглі фабрики не підтримують ці обєкти

Проект Factory в повному обсязі можна знайти на сторінці fileshtm сайту книги У нього включений також і клас BasicDaoFactory vb, що вимагає від клієнта вказівки типу джерела даних запитуваної обєкта Цей підхід не рекомендується використовувати з тієї ж причини, що і модель DAO Він включений в проект тільки для наочності

Джерело: Нільсен, Пол Microsoft SQL Server 2005 Біблія користувача : Пер з англ – М: ООО ІД Вільямс , 2008 – 1232 с : Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*