Шаблон загрузки бизнес-объекта
-
03-07-2019 - |
Вопрос
Проект, над которым я работаю, использует n-уровневую архитектуру.Наши слои следующие:
- Доступ к данным
- Бизнес-логика
- Хозяйствующие субъекты
- Презентация
Бизнес-логика переходит на уровень доступа к данным, а уровень представления переходит на уровень бизнес-логики, и все они ссылаются на бизнес-объекты.
Наши бизнес-структуры в основном соответствуют нашей модели данных 1-1.Для каждой таблицы у нас есть класс.Первоначально, когда разрабатывалась платформа, не учитывалось управление отношениями "мастер-деталь" или "потомок-родитель".Таким образом, вся бизнес-логика, доступ к данным и бизнес-объекты ссылались только на одну таблицу в базе данных.Как только мы начали разрабатывать приложение, быстро стало очевидно, что отсутствие этих взаимосвязей в нашей объектной модели серьезно вредит нам.
Все ваши слои (включая базу данных) генерируются из собственной базы метаданных, которую мы используем для управления нашим самодельным генератором кода.
Вопрос в том, каков наилучший способ загрузки или отложенной загрузки отношений в наших сущностях.Например, предположим, что у нас есть класс person, который имеет отношение master-child к таблице адресов.Это отображается в бизнес-объекте как свойство сбора адресов в объекте Person.Если у нас есть отношение "один к одному", то это будет отображаться как свойство единой сущности.Каков наилучший подход для заполнения и сохранения объектов отношений?Наши бизнес-объекты не имеют представления о уровне бизнес-логики, поэтому это не может быть сделано внутренне при вызове свойства get .
Я уверен, что для этого существует какая-то стандартная скороговорка.Есть какие-нибудь предложения?
Кроме того, одно предостережение заключается в том, что уровень DataAcess использует отражение для построения наших сущностей.Хранимые процедуры возвращают один результат selt на основе одной таблицы, и с помощью отражения мы заполняем наш бизнес-объект, сопоставляя имена свойств с именами столбцов.Так что выполнять объединения было бы сложно.
Решение
Я настоятельно рекомендую заглянуть в Fowler's Шаблоны корпоративной архитектуры книга.Есть несколько различных подходов к решению такого рода проблем, которые он хорошо описывает, включая отношения между сущностями.
Одним из наиболее привлекательных элементов был бы шаблон Unit Of Work, который в основном является сборщиком, который наблюдает за действиями, выполняемыми с вашими объектами, и как только вы закончите свое действие, он выполняет соответствующие вызовы базы данных и отправляет запрос к базе данных.Этот паттерн является одним из центральных понятий, используемых NHibernate на, который использует объект, реализующий IDisposable, чтобы сигнализировать об окончании "работы".Это позволяет вам обернуть ваши действия в using и поручить подразделению работы обрабатывать действия за вас.
Редактировать:Дополнительная информация
Это это ссылка на базовую классовую структуру единицы работы ... на самом деле не самая захватывающая вещь в мире.Фаулер приводит более подробную информацию в своей книге, некоторые из которых вы можете увидеть здесь.Вы также можете посмотреть на объект Session из NHibernate как на возможную реализацию ( мне удалось отследить Изессия интерфейс ... не уверен, где находится реализация)
Надеюсь, это поможет.
Другие советы
Подход, который я использовал в прошлом, заключается в том, чтобы сделать тип контейнера достаточно умным для извлечения требуемых объектов.например:
public class Relation<T>
{
private T _value;
private void FetchData()
{
if( LoadData != null ) {
LoadDataEventArgs args = new LoadDataEventArgs(typeof(T), /* magic to get correct object */);
LoadData(this, args);
_value = (T)args.Value;
}
}
public event EventHandler<LoadDataEventArgs> LoadData;
public T Value {
get {
if( _value == default(T) )
FetchData();
return _value;
}
set { /* Do magic here. */ }
}
}
Затем вы объявляете это в своей сущности следующим образом:
[RelationCriteria("ID", EqualsMyProperty="AddressID")]
public Relation<Address> Address {
get; set;
}
И именно загрузчик типа, который объявляет свойство Address, должен добавить обработчик к событию loadData.
Аналогичный класс реализует IList, чтобы предоставить вам отношение "один ко многим".
На каком языке вы говорите?То, что вы описали, - это именно то, что Entity Framework делает в .Net.Но вы не сообщили, какой язык вы используете, и я предполагаю, что вы не хотите переписывать какой-либо из своих слоев данных.