Связь между BLL и DAL
Настройка решения:
- DAL (библиотека классов)
- BLL (библиотека классов)
- Common (библиотека классов (некоторые общие функции - перечисления, ведение журнала, исключения,...))
- Приложение1 (Приложение Windows)
- Приложение2 (Приложение Windows)
- WebApp (веб-приложение)
- ...
Допустим, у меня есть объект Customer, который:
- таблица в SQL-сервере
- таблица CustomerDataTable в DAL
- Класс клиента в BLL
- класс BLL.Customer во всех приложениях
Какие объекты BLL и DAL должны использовать для общения - DataTable
или же List<Customer>
(например)? В первом случае логика BLL должна преобразовать объект Customer в DataTable и отправить его в DAL. Во втором случае уровень DAL должен знать о классе Customer, который находится на уровне BLL. Но оригинально DLL ссылается на DAL, а не наоборот...
Должен ли я поместить все классы в отдельную сборку, на которую ссылаются все остальные (Common, BusinessObjects, ...)? В этом случае я мог бы использовать класс Customer во всех моих проектах.
Должен ли я даже разделить DAL и BLL, когда я знаю, что только один BLL будет использовать мой DAL. В этом случае я мог бы объединить их в один проект.
PS - Я читаю о DataTables, и многие люди говорят, что мы не должны их использовать вообще. Какие варианты лучше? Может быть, пришло время изучить некоторые инструменты картирования ORM:)
4 ответа
На мой взгляд, вы должны иметь другой слой (отдельный DLL). Как и "домен", где вы будете хранить все объекты, как клиент. Затем просто включите во все более высокие уровни (DAL, BLL, UI и другие) в иерархию эту сборку.
Пример архитектуры может выглядеть так:
(База данных) <-> DAL <-> BL <-> UI
и на всех уровнях у вас будет доступ к "доменному" слою. DAL должен вернуть List, а не DataTable. На каком-то этапе процесса разработки вы можете захотеть использовать в DAL некоторые OMR, например NHibernate с, также, вероятно, вернет List.
Трудно ответить на этот общий вопрос, не зная предметную область достаточно хорошо. Я бы начал с размышлений о том, где наиболее вероятны будущие изменения, и попытался бы понять, где требуется гибкость.
моя следующая мысль - всего лишь предложение. не стесняйтесь рассматривать их и менять / игнорировать то, что вы считаете неуместным.
отделение DAL от BLL почти всегда хорошая идея. схема данных - это одна вещь, которая должна быть инкапсулирована и скрыта от остальной части приложения, поэтому оставьте свои DataTables, DataSets, ORM или любые другие решения скрытыми в DAL. BLL (и слои над ним) должны использовать простые типы данных (то есть простые классы). Я думаю, что было бы неплохо поместить эти классы в библиотеку классов Model, которая не имеет ссылок и может использоваться везде.
такое ощущение, что у вас слишком много уровней... вам действительно нужен класс Customer в BLL и еще один на уровне Application? могло бы быть, но я бы удостоверился и дважды обдумал это.
Исходя из моего опыта в одном из моих недавних проектов (веб-сайт о погоде с 200K уникальных посетителей ежедневно), мы использовали link2sql для доступа к данным (в основном данные только для чтения) и простые классы данных во всем нашем приложении ASP.Net MVC (конечно, как часть моделей / просмотр моделей). это работало довольно гладко, и мы могли легко изменить схему данных, не разбивая другие слои.
Что касается вашего последнего вопроса о DataTables, то эти объекты, если вы решите их использовать (я бы проголосовал), принадлежат исключительно вашему DAL. они не должны подвергаться воздействию других слоев, так как это создаст связь с этим конкретным классом. что если завтра MS придумает класс намного лучше? Не могли бы вы перейти сейчас, когда у вас есть тысячи ссылок по всем проектам на DataTables, его метод и свойства? было бы лучше просто изменить свой DAL для работы с классом NewAwsomeDataTable, а остальная часть вашего приложения, к счастью, неосведомлена.
надеюсь что помогло:)
Я бы использовал следующий шаблон, так как позже он позволит вам перейти на другую стратегию персистентности.
UI/Consumer <--- (view models) --> BLL <--- Models ----> DAL/Persistence
Здесь модели View потребляются вне BLL, а модели передаются через уровни BLL/DAL.
В вашем случае модель может быть чем угодно, что использует DAL - например, DataTables или позже, возможно, объектами ORM. BLL отвечает за отображение между моделью и моделью представления.
Что касается хранения типов в их собственных сборках - да, для моделей представлений и для обеспечения согласованности, да, и для моделей.
Хранение моделей и просмотр моделей отдельно предотвращает утечку постоянных стратегий за пределами BLL и, таким образом, допускает будущие изменения проекта в постоянстве.
Одним из преимуществ этого разделения является то, что потребители разных моделей представлений могут иметь разные модели представлений для одной и той же модели / объекта персистентности. Некоторые могут быть небольшими и иметь мало атрибутов, а другие - большими и функциональными. Это также позволяет вам вводить возможность автономной работы / отключения, так как модели представлений могут возвращаться в разное время, что позволяет вам выбирать стратегии объединения данных. Это также позволяет вам сохранять сущности (например, таблицы увеличиваются и меняют форму). Так как это похоже на реализацию.net, такие вещи, как AutoMapper, предоставляют много функциональных возможностей из коробки
Конечно, это может быть слишком излишним для вашего приложения - однако я все еще буду поддерживать отображение BLL, которое только сообщает модели представления всем потребителям BLL. Это должно дать вам достаточно развязки.
Задвинуть доменные сущности в dal - это опция, которая удаляет кривую зависимости, но может не соответствовать вашим намерениям. Это не неслыханно, хотя; Например, сущности с LINQ-to-SQL будут жить в DAL.
Другие опции:
- поместите их в общую нижнюю сборку (но это может оставить ваш BL довольно пустым)
- используйте IOC для удаления / реверса ссылки между BL/DAL
Здесь нет единственно правильных ответов.
Re DataTable; лично я согласен - я не фанат;) Однако их можно использовать успешно и разумно. Но если бы мне пришлось их использовать, я бы оставил их в DAL как деталь реализации, а не выставлял бы их выше этого.