Бізнес-об'єкти в рівні доступу до даних


12

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

Методи в моєму шарі доступу до даних (DAL коротко) досить прості. Вони відповідають збереженим процедурам у базі даних (іншого способу зателефонувати в неї, щоб зберегти чистоту), і вони містять ті самі параметри, що і процедури. Потім вони просто підключаються до бази даних і повертають результат запиту. Ось один приклад:

public int DeleteRecord(int recordId)
{
    recordId.RequireThat("recordId").NotZeroOrLess();

    List<SqlParameter> parameters = new List<SqlParameter>();
    parameters.Add(new SqlParameter { ParameterName = "@RecordId", SqlDbType = SqlDbType.Int, Direction = ParameterDirection.Input, Value = recordId});

    return this.ExecuteNonQuery("DeleteRecord", parameters.ToArray());
}

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

Однак, скажімо, в іншому методі DAL, я хочу завантажити запис. Моя процедура завантаження буде виконуватись selectsнад купою таблиць і повертати a DataSet, але я борюся з тим, чи повинен мій DAL створювати бізнес-об'єкти в рамках методу, використовуючи метод DataSet, або якщо мої бізнес-об'єкти повинні просто мати Load()метод, який отримує DataSetвід DAL, а потім в основному заповнює себе.

Якщо це зробити через DAL, це призведе до меншої логіки в бізнес-об'єктах (навіть якщо це лише логіка вибору, це все-таки логіка), але трохи натовпить DAL і дасть йому відчуття, ніби він справді робить щось, чого не повинен ' не робити.

Як ви думаєте, хлопці?


Чому ви не використовували Entity Framework?
jfrankcarr

@jfrankcarr - Чесно кажучи, головним чином тому, що я з ним не так знайомий, як повинен бути. Однак мені потрібно переробити свої таблиці та додати відповідні зовнішні ключі тощо, щоб Entity Framework розпізнавав відносини належним чином. Хоча з цікавості, хоч, якби я ним користувався, я б просто робив весь вибір, використовуючи рамки із самими Бізнес-об'єктами, чи все ж таки буде рішення про те, куди поставити ці запити LINQ?

Я рекомендую взяти час для вивчення EF. Спочатку це може здатися трохи запаморочливим, особливо, коли ви намагаєтесь зрівняти його з існуючою базою даних, яка має деякі попередні проблеми дизайну, але це того варто.
jfrankcarr

Ви також можете подивитися на NHibernate, якщо хочете розглянути інший варіант.
Дон 01001100

@jfrankcarr - я, безумовно, буду розглядати це, але як воно вписується в багатоярусну програму доступу до даних? Чи буде сама структура суб'єкта господарювання реалізована в самому DAL або в іншому шарі або навіть самих Бізнес-об'єктах?

Відповіді:


4

Ваш DAL повинен повернути ваші об'єкти даних

В ідеалі ваш DAL повинен бути об'єктом "чорної скриньки", який ваш код програми може використовувати для запиту об'єкта даних або маніпулювання існуючими об'єктами даних. Іноді між DAL та кодом програми Repository, який називається the , є ще один шар , який додатково розділяє два шари, хоча це не завжди потрібно.

Крім того, ви зазвичай не хочете, щоб ваші бізнес-об’єкти могли створювати самі. Це може викликати отвори в безпеці, де хтось може використовувати вашу бібліотеку, і створити новий екземпляр вашого об'єкта, зателефонувавши .Load(someId)до нього, і він зливає два рівні, які повинні бути повністю відокремленими.

Я також не рекомендую надавати .Load(DataSet ds)метод, оскільки якщо зміни набору даних змінюються, вам доведеться шукати об'єкти даних, які використовують цей набір даних, і змінювати їх. Простіше зберігати весь код доступу до даних в одному місці, тому якщо ви зміните запит доступу до даних, вам слід буде лише змінити рівень DAL.


Не впевнено, як від одного шару може залежати "повернення правильного об'єкта", якщо визначення "правильного об'єкта" буде проведено в іншому шарі.
TMN

@TMN Це було погано сформульовано. Я трохи змінив формулювання, оскільки ти маєш рацію, код програми повинен знати, про який об’єкт його просять.
Рейчел

@Rachel - Gotcha. Тож ви б рекомендували, щоб DAL повертав екземпляр того, який би мій бізнес-об’єкт був би, правда? Мене якось бентежить ваше формулювання "об'єктів даних", але я думаю, що це розумію. Таким чином, мій код міг запитувати бізнес-об’єкт там, де він потрібен (а не через них самих), просто зателефонувавши BusinessObject bo = DAL.LoadRecord(id);- звучить правильно? Логіка відображення запиту до самого БО міститиметься в DAL і тільки там.

1
@Scott Це правильно, хоча я б назвав метод DAL що - щось на зразок Getзамість Load, якCustomer c = DAL.GetCustomer(id);
Рахілі

2

Мій метод, ще до LINQ-To-SQL та Entity Framework, полягав у створенні інтерфейсу та бібліотеки абстрактних класів, які забезпечували "письмовий контракт" для зв'язку між різними шарами програми. Це іноді називають онтологією , визначенням робочої області. Все, що пройшло між шарами, використовувало цей "контракт".

Мені не подобається ідея передачі необроблених об’єктів набору даних із рівня даних у бізнес-рівень. Я бачив цей результат у ряді проблем, особливо при інтеграції застарілих джерел даних. Новим людям, які вступають у проект, також може бути дуже важко зрозуміти, звідки беруться дані. Нарешті, він вимагає, щоб ваш бізнес-рівень працював над обробкою даних безпосередньо з БД, що може призвести до ускладнень у дорозі.

Приклад, який у вас був, схожий на код, який я мав до LINQ. У мене був загальний клас функціонування БД, який я використовував всередині своїх DAL-об'єктів. Класи DAL читали б дані та вкладали їх у об'єкти «контракту». Скалярні результати, як ваш приклад видалення, повертають значення, як правило, булеве.


1
"Мені не подобається ідея передачі необроблених об'єктів набору даних із рівня даних у бізнес-рівень." Це. Тисячу разів, це.
Джошуа Сміт

@jfrankcarr - Мій DAL насправді реалізує інтерфейс, і я планую мати інтерфейси для всього, що передає дані від шару до шару, тому я думаю, що наші ідеї шаблонів відповідають. Тож чи рекомендуєте ви змінити методи, що повертають прямий результат ExecuteScalarзапитів, щоб повернути значення, що мають більше сенсу для бізнес-рівня, наприклад bool? Я думаю, інакше це дуже схожа відповідь на Рейчел.

Я, як правило, повертаю булеву форму для створення / оновлення / видалення дзвінків, якщо мені не потрібна кількість записуваних файлів. Наприклад, я можу повернути Int, якщо збережений додаток обробляє кілька рядків замовлення або щось подібне.
jfrankcarr

0

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


0

Я рекомендую вашим бізнес-об’єктам мати конструктор, щоб заповнити себе з набору результатів. Це видаляє з'єднання між вашим DAL та бізнес-шаром. Якщо ви хочете повністю ізолювати ці два, створіть просту карту стовпців name => значень пар зі свого набору результатів і передайте це конструктору.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.