Бизнес-объекты на уровне доступа к данным

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против кучи таблиц и возвращая DataSet, но я боролся с ли объектами моего DAL должен создать бизнес в рамках метода с использованием DataSet, или если мой Business Objects сами должен просто иметь Load()метод , который получает DataSetот DAL, а затем в основном заполняет себя.

Выполнение этого через DAL приведет к меньшему количеству логики в бизнес-объектах (даже если это всего лишь логика выбора, это по-прежнему логика), но немного соберет DAL и заставит его почувствовать, что он действительно делает то, что не должен ' не делать.

Что вы ребята думаете?


источник
Почему вы не использовали Entity Framework?
jfrankcarr
@jfrankcarr - Если честно, главным образом потому, что я не настолько знаком с ним, как следовало бы. Однако мне нужно будет переработать мои таблицы и добавить соответствующие внешние ключи и т. Д., Чтобы Entity Framework распознавал отношения должным образом. Просто из любопытства, если бы я использовал его, я бы просто сделал весь выбор, используя каркас с самими бизнес-объектами, или все еще было бы решение относительно того, куда поместить эти запросы LINQ?
Я бы рекомендовал потратить время на изучение EF. Поначалу это может показаться немного сложным, особенно когда вы пытаетесь привести его в соответствие с существующей базой данных, которая имеет некоторые ранее существовавшие проблемы проектирования, но это того стоит.
jfrankcarr
Вы также можете посмотреть на NHibernate, если вы хотите посмотреть на другой вариант.
Дон 01001100
@jfrankcarr - я определенно посмотрю на это, но как оно вписывается в многоуровневое приложение для доступа к данным? Будет ли сама сущностная структура реализована в самом DAL, или на другом уровне, или даже в самих бизнес-объектах?

Ответы:

4

Ваш DAL должен вернуть ваши объекты данных

В идеале ваш DAL должен быть объектом «черного ящика», который код вашего приложения может использовать для запроса объекта данных или манипулирования существующими объектами данных. Иногда между DAL и кодом приложения ставится еще один уровень Repository, который далее разделяет два уровня, хотя это не всегда необходимо.

Кроме того, вы обычно не хотите, чтобы ваши бизнес-объекты могли создавать сами. Это может вызвать дыры в безопасности, когда кто-то может использовать вашу библиотеку, и создать новый экземпляр вашего объекта, вызвав .Load(someId)его, и он объединит два слоя, которые должны быть полностью разделены.

Я также не рекомендую предоставлять .Load(DataSet ds)метод, потому что, если определение набора данных изменится, вам придется выследить объекты данных, которые используют этот набор данных, и изменить их. Проще хранить весь код доступа к данным в одном месте, поэтому, если вы измените запрос доступа к данным, вам нужно будет только изменить уровень DAL.

Рейчел
источник
Не уверен, как один слой может зависеть от «возврата правильного объекта», если определение «правильного объекта» содержится в другом слое.
TMN
@ TMN Это было плохо сформулировано. Я немного изменил формулировку, потому что вы правы, код приложения должен знать, какой объект он запрашивает.
Рэйчел
@ Рейчел - Попалась. Таким образом, вы бы порекомендовали, чтобы DAL возвращал экземпляр того, чем был бы сам мой бизнес-объект, верно? Я был немного смущен вашей формулировкой «объектов данных», но я думаю, что понимаю ее. Таким образом, мой код может запрашивать бизнес-объект из любого места (не через них), просто вызывая BusinessObject bo = DAL.LoadRecord(id);- звучит правильно? Логика для сопоставления запроса с самим BO должна содержаться в DAL и только там.
1
@Scott Это правильно, хотя я бы назвал метод DAL что - то вроде Getвместо Load, какCustomer c = DAL.GetCustomer(id);
Рахили
2

Мой метод, даже до LINQ-To-SQL и Entity Framework, заключался в том, чтобы иметь интерфейс и абстрактную библиотеку классов, которая обеспечивала «письменный контракт» для взаимодействия между различными уровнями приложения. Это иногда называют онтологией , определением рабочей области. Все, что проходило между слоями, использовало этот «контракт».

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

Пример кода у вас выглядит аналогично коду, который я имел до LINQ. У меня был общий класс функций БД, который я использовал внутри своих объектов DAL. Классы DAL будут считывать данные и помещать их в объекты «контракта». Скалярные результаты, как и ваш пример удаления, будут возвращать значение, обычно логическое.

jfrankcarr
источник
1
«Мне не нравится идея передачи необработанных объектов набора данных из уровня данных в бизнес-уровень». Этот. Тысячу раз это.
Джошуа Смит
@jfrankcarr - Мой DAL действительно реализует интерфейс, и я планирую иметь интерфейсы для всего, что передает данные от слоя к слою, поэтому я думаю, что наши идеи шаблонов совпадают. Поэтому вы рекомендуете изменить методы, которые возвращают прямой результат ExecuteScalarзапросов, чтобы возвращать значения, которые имеют больше смысла для бизнес-уровня, например bool? Я думаю иначе, это очень похоже на ответ Рэйчел.
Я обычно возвращаю логическое значение для вызовов создания / обновления / удаления, если мне не нужно количество затронутых записей. Например, я могу вернуть int, если хранимый процесс обрабатывает несколько строк заказа или что-то в этом роде.
jfrankcarr
0

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

Ryathal
источник
0

Я бы порекомендовал вашим бизнес-объектам иметь конструктор, чтобы они заполняли себя из набора результатов. Это устраняет связь между вашим DAL и бизнес-уровнем. Если вы хотите полностью изолировать их, создайте простую карту пар столбцов имя => значение из набора результатов и передайте ее конструктору.

TMN
источник