Entity Framework и предотвращение анемичной доменной модели

11

В нашей бизнес-логике мы иногда определяем методы примерно так:

User.ResetCourse(Course courseToReset)

Проблема в том, что и Пользователь, и Курс являются объектами прокси Entity Framework. Это означает, что когда мы обращаемся к свойствам навигации для пользователя или курса, это может привести к огромному удару по базе данных, поскольку эти объекты не являются IQueryable, поэтому он проходит через них в обычном режиме.

Чтобы решить эту проблему, мы изменили подпись:

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 в расширенном примере. Конечно, Active Record не поддерживается в DDD и, в целом, является плохим выбором для любого сложного приложения.
Рибальд Эдди

Ответы:

8

Проблема в том, что вы используете объекты EF в качестве объектов домена. EF объекты - это модели данных, а не бизнес-модели.

Вам нужно объявить бизнес-объекты, которые дают вам свободу делать то, что вам нужно, а затем извлекать и хранить их в хранилище. Ваш репозиторий будет сопоставлять сущности EF с вашими бизнес-сущностями. Объекты EF никогда не должны использоваться за пределами ваших репозиториев.

TheCatWhisperer
источник
0

Вы, вероятно, можете избежать этого, сделав что-то вроде:

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

Или что-то в этом роде, в любом случае, если вы поймете мой дрейф. Похоже, что подход, который вы использовали с первоначальным способом, который вы описали, связан с производительностью и не обязательно связан со структурой домена. Так что на самом деле вы должны рассмотреть решение проблемы производительности на уровне сервиса, но можете сохранить поведение в домене. Было бы полезно узнать, что означает сброс пользователя / курса в этом контексте, если вы хотите получить лучший ответ.

RibaldEddie
источник
-1

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

Уди Дахан написал пост, описывающий общий подход, который можно адаптировать к Entity Framework.

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

pnschofield
источник