Так что я создавал уровень доступа к данным через 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 и заставит его почувствовать, что он действительно делает то, что не должен ' не делать.
Что вы ребята думаете?
Ответы:
Ваш DAL должен вернуть ваши объекты данных
В идеале ваш DAL должен быть объектом «черного ящика», который код вашего приложения может использовать для запроса объекта данных или манипулирования существующими объектами данных. Иногда между DAL и кодом приложения ставится еще один уровень
Repository
, который далее разделяет два уровня, хотя это не всегда необходимо.Кроме того, вы обычно не хотите, чтобы ваши бизнес-объекты могли создавать сами. Это может вызвать дыры в безопасности, когда кто-то может использовать вашу библиотеку, и создать новый экземпляр вашего объекта, вызвав
.Load(someId)
его, и он объединит два слоя, которые должны быть полностью разделены.Я также не рекомендую предоставлять
.Load(DataSet ds)
метод, потому что, если определение набора данных изменится, вам придется выследить объекты данных, которые используют этот набор данных, и изменить их. Проще хранить весь код доступа к данным в одном месте, поэтому, если вы измените запрос доступа к данным, вам нужно будет только изменить уровень DAL.источник
BusinessObject bo = DAL.LoadRecord(id);
- звучит правильно? Логика для сопоставления запроса с самим BO должна содержаться в DAL и только там.Get
вместоLoad
, какCustomer c = DAL.GetCustomer(id);
Мой метод, даже до LINQ-To-SQL и Entity Framework, заключался в том, чтобы иметь интерфейс и абстрактную библиотеку классов, которая обеспечивала «письменный контракт» для взаимодействия между различными уровнями приложения. Это иногда называют онтологией , определением рабочей области. Все, что проходило между слоями, использовало этот «контракт».
Мне не нравится идея передачи необработанных объектов набора данных из уровня данных в бизнес-уровень. Я видел этот результат в ряде проблем, особенно при интеграции устаревших источников данных. Для новых людей, вступающих в проект, также может быть очень сложно понять, откуда поступают данные. Наконец, это требует, чтобы ваш бизнес-уровень занимался обработкой данных непосредственно из БД, что может привести к осложнениям в будущем.
Пример кода у вас выглядит аналогично коду, который я имел до LINQ. У меня был общий класс функций БД, который я использовал внутри своих объектов DAL. Классы DAL будут считывать данные и помещать их в объекты «контракта». Скалярные результаты, как и ваш пример удаления, будут возвращать значение, обычно логическое.
источник
ExecuteScalar
запросов, чтобы возвращать значения, которые имеют больше смысла для бизнес-уровня, напримерbool
? Я думаю иначе, это очень похоже на ответ Рэйчел.Ваш DAL должен вернуть набор данных. Возвращенный набор данных должен быть бизнес-объектом, с ним ничего не нужно делать, кроме проверки наличия ожидаемых данных. Если вам нужно сделать больше с этим, то вы либо пытаетесь сделать слишком много в одной хранимой процедуре, либо не возвращаете данные должным образом в хранимой процедуре.
источник
Я бы порекомендовал вашим бизнес-объектам иметь конструктор, чтобы они заполняли себя из набора результатов. Это устраняет связь между вашим DAL и бизнес-уровнем. Если вы хотите полностью изолировать их, создайте простую карту пар столбцов имя => значение из набора результатов и передайте ее конструктору.
источник