Entity Framework та уникнення анемічної моделі домену


11

У нашій бізнес-логіці періодично є методи, визначені приблизно так:

User.ResetCourse(Course courseToReset)

Проблема полягає в тому, що і користувач, і курс є проксі-об'єктами Entity Framework. Це означає, що коли ми потрапляємо на властивості навігації або на користувачі, або на курс, це може спричинити величезне потрапляння в базу даних, тому що ці об'єкти не є IQueyable, тому він ітерує через них нормально.

Щоб вирішити це, ми змінили підпис на:

User.ResetCourse(MyDBContext db, Course courseToReset)

Це означає, що ми можемо безпосередньо запитувати базу даних для ефективного внесення необхідних нам змін, але передача контексту Бази даних бізнес-об’єкту просто здається таким неправильним.

Пізніше ми перенесли на користувацький рівень обслуговування, що означає, що у нас є щось на кшталт:

CourseService.ResetForUser(Course courseToReset, User forUser)

У цій службі є посилання на DBContext, який вводиться під час створення, але тепер наші бізнес-об'єкти - це лише пакети даних без поведінки (тобто, анемічна модель домену).

Як ми можемо цього уникнути?


11
Такого роду звуки, ніби ви щойно потрапили до усвідомлення того, що моделі фреймворку сутності насправді є DTO, а зовсім не доменна модель. Ви насправді намагаєтеся зробити DDD? Якщо ні, то, мабуть, це не має значення.
Містер Кохез

3
ADM plus послуги - це хороша архітектура для багатьох речей
Ewan


2
@JohnWu - це дуже упереджена стаття. Дійсно, вона містить "Strawman" версію багатої доменної моделі, включаючи шаблон активного запису у приклад багатих. Звичайно, Active Record не підтримується в DDD і взагалі є поганим вибором для будь-якого складного застосування.
RibaldEddie

Відповіді:


8

Проблема полягає в тому, що ви в першу чергу використовуєте об'єкти EF як доменні об'єкти. Об'єкти EF - це моделі даних НЕ бізнес-моделі.

Вам потрібно оголосити бізнес-об’єкти, які дають вам свободу робити так, як вам потрібно, а потім отримати та зберігати їх у сховищі. У вашому сховищі буде відображено об’єкти EF у ваші суб’єкти господарювання. Об'єкти EF ніколи не повинні використовуватися поза вашими сховищами.


0

Ви можете, можливо, уникнути цього, зробивши щось на кшталт:

CourseService.prepareForUserCourseReset(DBContext db);
User.reset();
Course.reset();
CourseService.completeUserCourseReset(DBContext db);

Або щось для цього, все-таки, якщо ви зловили мій дрейф. Це звучить як підхід, який ви маєте з початковим способом, який ви описали, пов'язаний з продуктивністю , а не обов'язково пов'язаний зі структурою домену. Тому дійсно слід розглянути питання про ефективність на рівні сервісу, але можна зберегти поведінку в домені. Було б корисно знати, що означає скинути Користувача / Курс у цьому контексті, якщо ви хочете кращої відповіді.


-1

Традиційно це вирішується за допомогою стратегії вибору для кожного випадку використання, який дає змогу Entity Framework прагнути завантажувати необхідні асоціації для початкового запиту за допомогою IQueryable.Include ().

Уді Дахан написав пост, в якому описує загальний підхід, який можна адаптувати до Entity Framework.

http://udidahan.com/2007/09/16/fetching-strategy-nhibernate-implementation-available/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.