Приложение N-уровневой базы данных без использования ORM. Как пользовательский интерфейс определяет, какие данные ему нужны для отображения?

StackOverflow https://stackoverflow.com/questions/1524367

Вопрос

Я ищу здесь подсказки и информацию, я сделаю это CW, так как подозреваю, что здесь нет ни одного правильного ответа.Это для C#, поэтому ниже я сделаю несколько ссылок на Linq.Я также прошу прощения за длинный пост.Позвольте мне суммировать вопрос здесь, а затем следует полный вопрос.

Краткое содержание:Как в четырехуровневом приложении UI/BLL/DAL/DB можно внести изменения в пользовательский интерфейс, чтобы отобразить больше столбцов (скажем, в сетке), избежать утечки через уровень бизнес-логики на уровень доступа к данным, чтобы закрепиться? данных для отображения (при условии, что они уже есть в базе данных).


Предположим, что многоуровневое приложение имеет 3 (4) слоя:

  • Пользовательский интерфейс (UI)
  • Уровень бизнес-логики (BLL)
  • Уровень доступа к данным (DAL)
  • База данных (БД;четвертый слой)

В этом случае DAL отвечает за создание операторов SQL и их выполнение в базе данных, возвращая данные.

Является ли единственный способ «правильно» построить такой слой просто всегда выполнять «выбрать *»?Для меня это категорический «нет-нет», но позвольте мне объяснить, почему мне интересно.

Допустим, я хочу в своем пользовательском интерфейсе отображать всех сотрудников, имеющих активную трудовую книжку.Под «активным» я подразумеваю, что записи о приеме на работу содержат даты от и до сегодняшнего дня (или, возможно, даже дату, которую я могу установить в пользовательском интерфейсе).

В этом случае, предположим, я хочу разослать электронное письмо всем этим людям, поэтому у меня есть некоторый код в BLL, который гарантирует, что я еще не отправлял электронное письмо тем же людям и т. д.

Для BLL требуются минимальные объемы данных.Возможно, он вызывает уровень доступа к данным, чтобы получить список активных сотрудников, а затем выполняет вызов, чтобы получить список отправленных им электронных писем.Затем он присоединяется к ним и создает новый список.Возможно, это можно было бы сделать с помощью уровня доступа к данным, это не важно.

Важно то, что для бизнес-уровня на самом деле требуется не так уж много данных.Возможно, ему просто нужен уникальный идентификатор для каждого сотрудника в обоих списках, чтобы он совпадал, а затем сказать: «Это уникальные идентификаторы тех, кто активен, которым вы еще не отправили электронное письмо».Должен ли я затем создать код DAL, который создает операторы SQL, которые извлекают только то, что нужно бизнес-уровне?Т.е.просто "ВЫБРАТЬ id ИЗ сотрудников ГДЕ..."?

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

Как пользовательский интерфейс получает эти данные?Должен ли я изменить DAL, чтобы гарантировать возврат достаточного количества данных обратно в пользовательский интерфейс?Должен ли я изменить BLL, чтобы убедиться, что он возвращает достаточно данных для пользовательского интерфейса?Если структуры объектов или данных, возвращаемые из DAL обратно в BLL, также могут быть отправлены в пользовательский интерфейс, возможно, BLL не требует особых изменений, но тогда требования пользовательского интерфейса влияют на уровень, выходящий за рамки того, с чем он должен взаимодействовать. .А если два мира оперируют разными структурами данных, изменения, вероятно, придется внести в оба.

И что тогда, когда пользовательский интерфейс будет изменен, чтобы помочь пользователю еще больше, добавив больше столбцов, насколько глубоко мне придется зайти, чтобы изменить пользовательский интерфейс?(при условии, что данные уже присутствуют в базе данных, поэтому никаких изменений там не требуется.)

Одно из предложенных предложений — использовать Linq-To-SQL и IQueryable, чтобы если DAL, который имеет дело с тем, что (например, какие типы данных) и почему (как в предложениях WHERE), возвращал IQueryables, BLL мог бы потенциально вернуть их в пользовательский интерфейс, который затем сможет создать Linq-запрос, который получит необходимые ему данные.Затем код пользовательского интерфейса может получить необходимые ему столбцы.Это будет работать, поскольку с IQuerables пользовательский интерфейс фактически выполнит запрос, а затем сможет использовать «выбрать новый { X, Y, Z }», чтобы указать, что ему нужно, и даже присоединиться к другим таблицам, если необходимо.

Мне это кажется грязным.Пользовательский интерфейс сам выполняет код SQL, даже если он скрыт за интерфейсом Linq.

Но для того, чтобы это произошло, BLL или DAL не должно быть разрешено закрывать соединения с базой данных, а в мире типа IoC служба DAL может быть удалена немного раньше, чем хотелось бы коду пользовательского интерфейса, так что Запрос Linq может просто закончиться исключением «Невозможно получить доступ к удаленному объекту».

Поэтому я ищу указатели.Как далеко мы находимся?Как ты с этим справляешься?Я считаю тот факт, что изменения в пользовательском интерфейсе будут просачиваться через BLL в DAL, очень плохим решением, но сейчас не похоже, что мы можем добиться большего.

Пожалуйста, скажи мне, какие мы глупые, и докажи, что я неправ?

И обратите внимание, что это устаревшая система.Изменение схемы базы данных еще не рассматривалось в течение многих лет, поэтому решение использовать объекты ORM, которые по сути выполняли бы эквивалент «выбрать *», на самом деле не является вариантом.У нас есть несколько больших таблиц, которые мы бы не хотели перемещать по всему списку слоев.

Это было полезно?

Решение

Используйте концепцию модели представления (или объектов передачи данных), которая является вариантом использования пользовательского интерфейса.Задача BLL будет взять эти объекты и, если данные неполные, запросить дополнительные данные (которые мы называем моделью).Тогда BLL сможет принять правильное решение о том, какие модели представления возвращать.Не позволяйте особенностям вашей модели (данных) проникать в пользовательский интерфейс.

UI <-- (viewmodel) ---> BLL <-- (model) --> Peristence/Data layers

Такое разделение позволяет лучше масштабировать приложение.Я думаю, что независимость от персистентности естественным образом выпадает из этого подхода, поскольку построение и спецификация моделей представлений могут быть гибко реализованы в BLL с использованием linq2ql или другой технологии orm.

Другие советы

Эту проблему решить совсем не просто.Я видел много попыток (включая описанный вами подход IQueryable), но ни одна из них не была идеальной.К сожалению, мы все еще ждем идеального решения.До тех пор нам придется мириться с несовершенством.

Я полностью согласен с тем, что нельзя допускать, чтобы проблемы DAL просачивались на верхние уровни, поэтому необходим изолирующий BLL.

Даже если у вас нет возможности переопределить технологию доступа к данным в вашем текущем проекте, все равно полезно подумать о модели предметной области с точки зрения постоянного незнания.Следствием незнания постоянства является то, что каждый объект предметной области представляет собой автономную единицу, которая не имеет понятия о таких вещах, как столбцы базы данных.Лучше всего обеспечивать целостность данных как инварианты в таких объектах, но это также означает, что в созданный объект домена будут загружены все составляющие его данные.Это предложение «или-или», поэтому ключевым моментом становится поиск хорошей модели предметной области, которая гарантирует, что каждый объект предметной области содержит (и должен быть загружен) «подходящий» объем данных.

Слишком детализированные объекты могут привести к болтливости интерфейсов DAL, а слишком детализированные объекты могут привести к загрузке слишком большого количества нерелевантных данных.

Очень важным упражнением является анализ и правильное моделирование агрегатов модели предметной области, чтобы они обеспечивали правильный баланс.Книга Доменно-ориентированный дизайн содержит некоторые очень поучительные анализы агрегатов моделирования.

Другая стратегия, которая может оказаться полезной в этом отношении, — стремиться максимально применять «принцип Голливуда».Основная проблема, которую вы описываете, касается запросов, но если вы сможете переключить свое внимание на более ориентированное на команды, вы сможете определить некоторые более грубые интерфейсы, которые не требовать вы всегда загружаете слишком много данных.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top