#.net #vb.net #data-access-layer
Вопрос:
Я использую следующий код в классе JCProperty для извлечения данных из DAL:
Dim x As JCProperty
x = JCPropertyDB.GetProperty(PropertyID)
If Not x Is Nothing Then
Me.PropertyID = x.PropertyID
Me.AddressLine1 = x.AddressLine1
Me.AddressLine2 = x.AddressLine2
Me.AddressLine3 = x.AddressLine3
Me.AddressCity = x.AddressCity
Me.AddressCounty = x.AddressCounty
Me.AddressPostcode = x.AddressPostcode
Me.TelNo = x.TelNo
Me.UpdatedOn = x.UpdatedOn
Me.CreatedOn = x.CreatedOn
Me.Description = x.Description
Me.GUID = x.GUID
End If
Это работает нормально, но требует, чтобы объект DAL (JCPropertyDB) знал о бизнес-объекте (JCProperty), и я эффективно создаю и заполняю один и тот же объект дважды (один раз в DAL, чтобы вернуться в BL, а затем снова в объекте BL, чтобы заполнить себя).
Я что-то здесь упускаю, я знаю, что должен быть лучший способ!
Фактически мне нужно назначить «Мне = x», что недопустимо. Кто-нибудь может меня вразумить?
Ответ №1:
Вы находитесь на правильном пути, однако немного упускаете один момент.
Как правило, ваш уровень доступа к данным (DAL) возвращает объекты передачи данных (DTO) из вашей базы данных. Это обычные старые объекты CLR (POCO), которые не содержат бизнес-логики, просто свойства, более или менее соответствующие таблицам базы данных.
Затем у вас будет код, который создает модель домена из этих DTO, называемую Сопоставителем данных. Классы в модели домена могут иметь похожие имена (т. е. CustomerDTO -> Customer), но в дополнение к данным они будут содержать правила проверки и, возможно, другую бизнес-логику.
Именно эту модель домена вы затем используете на своем бизнес-уровне, а не фактические DTO. Это означает, что если вы измените DTO, возвращенные из DAL (т. Е. Путем внедрения нового инструмента ORM), вам нужно будет только изменить свой картограф данных, при условии, что модель данных останется прежней.
Я рекомендую изучить шаблоны архитектуры корпоративных приложений Мартина Фаулера для шаблонов доступа к данным.
Ответ №2:
Не уверен, что это ответит на ваш вопрос, но важно то, что модель домена не зависит от отображения и не зависит от хранилища. Это часто обозначается как разделение интересов. Идея состоит в том, чтобы ослабить связи и создать простую систему, в которой объекты не имеют нескольких совершенно разных обязанностей.
Поэтому я бы позволил DAL напрямую создавать бизнес-объекты, но убедитесь, что я не загрязняю свои бизнес-объекты чем-либо, связанным с DAL. Точно так же я не хочу загрязнять их специфичными для пользовательского интерфейса вещами, такими как HTML. На мой взгляд, это нормально, что и бизнес-уровень, и DAL, и уровень пользовательского интерфейса имеют зависимости от модели домена, однако не нормально иметь зависимости от модели домена и от этих других компонентов.
Чтобы ослабить соединения, вам может помочь использование пружины или любого другого контейнера для инъекций зависимостей вместе с интерфейсами и проводкой.
Воссоздавая один и тот же объект в каждом слое, вы нарушаете принцип DRY (не повторяйтесь), вводите код котельной плиты и увеличиваете вероятность появления где-либо ошибки.
Ответ №3:
Лично я ленив. Я обычно делаю что-то вроде:
class JCProperty : inherits JCPropertyDB
{
New()
{
MyBase.New()
GetProperty(PropertyID)
}
}
Затем вы в основном закончите, пока у вас не появится какая-то дополнительная функциональность в классе JCProperty, которая должна быть «поверх» функциональности, уже существующей в JCPropertyDB. Затем вы переопределяете методы JCPropertyDB, чтобы сначала вызвать базовый метод, а затем добавить новую функциональность.
Рон
Комментарии:
1. Именно этого мне не хватало! Ваше здоровье.
Ответ №4:
Проверьте: http://www.icemanind.com/layergen.aspx
Ответ №5:
Я принимал BOs и отправлял обратно BOs из DAL через шаблон моста и модель поставщика. Я не вижу смысла в DTO, если только я не боялся тяжелой сериализации (скажем, веб-службы или JSON). Мой подход состоял в том, чтобы абстрагировать уровень данных и бизнес-уровень через интерфейс и обеспечить анонимный уровень данных, вводимый в бизнес-объект. Это означает, что я могу подключить любой уровень данных, реализовать интерфейс, который имеет универсальные методы загрузки и сохранения и который затем доступен через мой доменный уровень. В BL нет кода DAL — просто вызов предоставленного и абстрагированного уровня данных. Мой вызов на уровень данных управляется шаблоном поставщика (без прямой ссылки), и я просто делаю:
public class Person : IBusinessObject<Person>
{
protected IDataLayer<T> dataLayer;
Person Load() { this.dataLayer.Load(this); }
}
в том слое данных, который у меня есть…
public class PersonMapper : IDataLayer<Person>
{
Person Load(Person person) {
...get DB stuff...map to person...decorate object...
return person;
}
}
Я все еще не знаю, хорошо ли это, но для меня это работает довольно хорошо. Мне также удалось получить ленивую загрузку для вложенных объектов с помощью отражения.