Добавление бизнес-уровня в ADO .NET Entity Framework - PullRequest
7 голосов
/ 11 января 2009

Я работаю над своим первым проектом .NET (.NET 3.5, ADO.NET и C #). Мы создали наши модели сущностей и пытаемся создать чистый слой бизнес-объектов.

У нас есть базовая модель сущностей, и мы хотим добавить определенную семантику бизнес-уровня в средства доступа к данным по умолчанию (свойства навигации и т. Д.).

Например, давайте предположим, что у нас есть отношение многие ко многим между Person и BankAccounts. Давайте предположим, что на бизнес-уровне мы хотели бы добавить возможность заблокировать учетную запись. Теперь нам нужна возможность навигации от человека к:

  • все их банковские счета,
  • их незамерзающие банковские счета и
  • их замороженные банковские счета.

Естественно, мы хотели бы установить номинальный регистр по умолчанию: если я перейду на Person.BankAccounts(), я бы хотел, чтобы он возвращал их не замороженные аккаунты. Я мог бы добавить свойства навигации Person.FrozenBankAccounts() и Person.AllBankAccounts().

Оба подхода, которые мы придумали, похоже, имеют достаточное количество запаха кода.

  1. Мы не можем найти способ переопределить методы модели сущностей. Поэтому оставьте Person.BankAccounts() в качестве средства доступа, которое возвращает все банковские счета. Затем мы добавляем Person.FrozenBankAccounts() и Person.NonFrozenBankAccounts().
  2. Добавьте еще один явный слой к базе кода, который оборачивает все обращения к BankAccounts.

При подходе 1 проблема заключается в том, что номинальное экономическое обоснование (доступ к незамерзшим банковским счетам) является наиболее неинтуитивным названием метода лота.

При подходе 2, когда мы создаем подклассы объектов из слоя модели сущностей, мы должны переопределить каждый метод, чтобы гарантировать, что он не вернет объекты из нижележащего слоя. Итак, мы создаем BL_Person, который имеет метод BankAccounts(), который возвращает коллекцию BL_BankAccount объектов. Но в этом случае весь этот код кажется немного глупым.

Есть ли лучший подход, чем два, которые мы рассмотрели? Если нет лучшего подхода, какой из двух описанных мною кажется лучшим решением (учитывая, что у нас есть что-то вроде 50+ классов, с которыми нам нужно работать)?

Примечание: Во время поиска в Интернете я обнаружил открытое письмо в Microsoft под названием ADO .NET Entity Framework Голосование об отсутствии доверия , в котором, как представляется, нет хороший способ добавить четкое разделение проблем.

Ответы [ 4 ]

4 голосов
/ 11 января 2009

У меня нет опыта работы с LINQ to Entities, но ваш вопрос зазвонил. В моем последнем проекте у меня были почти такие же проблемы с другим ORM. Вместо того, чтобы позволить клиентам уровня бизнес-объектов напрямую использовать сгенерированные классы ORM или дублировать все классы и реализовать массу функций пересылки, я определил интерфейсы. Клиенты вашего уровня бизнес-объектов будут видеть только эти интерфейсы, а ваши классы сущностей будут реализовывать эти интерфейсы со следующими преимуществами:

  • В простом случае (без бизнес-логики) затраты на разработку интерфейсов минимальны. Для большинства членов вам не нужно реализовывать функции пересылки, просто «извлеките» класс сущности из интерфейса и покончите с этим
  • В случае, о котором вы говорите, в интерфейсе вы можете иметь свойство BankAccounts и через явную реализацию интерфейса пересылать его в NonFrozenBankAccounts реализующей сущности. Конечно, вы также можете добавить любые виды проверок, которые вы хотите
  • В качестве дополнительного преимущества вы можете легко заменить базовый уровень персистентности, не внося видимых изменений в код клиента
1 голос
/ 12 апреля 2011

Вы можете добавить два новых типа сущностей, которые наследуются от учетной записи
- RegularAccount и FrozenAccount
и добавьте свое поле IsFrozen в качестве условия наследования (таблица для иерархии).

Затем вы можете удалить ассоциацию из «Персона» в «Аккаунт» и создать две новые ассоциации:

Лицо, зарегистрированное в RegularAccount, назовите свойство навигации на лице "Аккаунты".

Person to FrozenAccount, имя свойства навигации для лица "FrozenAccounts".

0 голосов
/ 20 февраля 2009

Один из способов сделать это был бы так:

  1. Определите свойство AllBankAccounts (возможно, даже сделайте его приватным).
  2. Определите свойство BankAccounts в частичном классе Person. Свойство может быть выражено в терминах AllBankAccounts с использованием LINQ, то есть AllBankAccounts.Where (a =>! A.IsFrozen)
  3. Определите свойство FrozenBankAccounts в частичном классе Person, как в шаге 2.

Надеюсь, это поможет.

0 голосов
/ 11 января 2009

Ditch EF в пользу NHibernate .

Путь NHibernate: вы создаете бизнес-объектов и сообщаете NHibernate, как эти бизнес-объекты должны быть сохранены в базе данных. Сами бизнес-объекты не знают о том, как они сохраняются или загружаются, или что используется NHibernate. Это называется "невежество постоянства". Кроме того, вы можете указать NHibernate сохранять и загружать бизнес-объекты практически любым удобным для вас способом. Он имеет хорошую поддержку для сценария, который вы описываете.

Прекратить запись слоев доступа к данным и прекратить их генерацию кода. Используйте настоящий мужской ORM .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...