Entity Framework et éviter le modèle de domaine anémique

11

Dans notre logique métier, nous avons parfois des méthodes définies quelque chose comme ceci:

User.ResetCourse(Course courseToReset)

Le problème est que l'utilisateur et le cours sont des objets proxy Entity Framework. Cela signifie que lorsque nous atteignons les propriétés de navigation sur User ou Course, cela peut causer un énorme succès à la base de données car ces objets ne sont pas IQueryable, donc il les parcourt normalement.

Pour résoudre ce problème, nous avons changé la signature en:

User.ResetCourse(MyDBContext db, Course courseToReset)

Cela signifie que nous pouvons interroger directement la base de données pour apporter les modifications dont nous avons besoin de manière efficace, mais passer le contexte de la base de données à un objet métier semble tellement mal.

Nous avons ensuite migré vers l'utilisateur une couche de service, ce qui signifie que nous avons quelque chose comme:

CourseService.ResetForUser(Course courseToReset, User forUser)

Ce service fait référence au DBContext injecté lors de la création, mais maintenant nos objets métier ne sont que des sacs de données sans comportement (c'est-à-dire un modèle de domaine anémique).

Comment éviter cela?

Steve
la source
11
On dirait que vous venez de réaliser que les modèles de structure d'entité sont en fait des DTO, et pas vraiment du tout un modèle de domaine. Essayez-vous réellement de faire DDD? Sinon, cela n'a probablement pas d'importance.
M. Cochese
3
Les services ADM plus sont une bonne architecture pour beaucoup de choses
Ewan
2
@JohnWu c'est un article très biaisé. En effet, il contient une version "Strawman" d'un modèle de domaine riche, en incluant le modèle Active Record dans l'exemple riche. Certes, Active Record n'est pas adopté en DDD et est en général un mauvais choix pour toute application complexe.
RibaldEddie

Réponses:

8

Le problème est que vous utilisez les objets EF comme objets de domaine en premier lieu. Les objets EF sont des modèles de données PAS des modèles commerciaux.

Vous devez déclarer des objets métier qui vous donnent la liberté de faire ce dont vous avez besoin, puis les récupérer et les stocker avec un référentiel. Votre référentiel mappera les entités EF à vos entités commerciales. Les objets EF ne doivent jamais être utilisés en dehors de vos référentiels.

TheCatWhisperer
la source
0

Vous pouvez probablement l'éviter en faisant quelque chose comme:

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

Ou quelque chose à cet effet, de toute façon, si vous attrapez ma dérive. Cela ressemble à l'approche que vous avez avec la manière initiale que vous avez décrite est liée aux performances , et pas nécessairement liée à la structure du domaine. Donc, vous devriez vraiment envisager de résoudre le problème de performances dans la couche de service, mais vous pouvez conserver le comportement dans le domaine. Il serait utile de savoir ce que signifie réinitialiser l'utilisateur / le cours dans ce contexte également si vous voulez une meilleure réponse.

RibaldEddie
la source
-1

Traditionnellement, cela est résolu en utilisant une stratégie de récupération pour chaque cas d'utilisation qui indique à Entity Framework de charger avec impatience les associations nécessaires sur la requête initiale à l'aide de IQueryable.Include ().

Udi Dahan a écrit un article qui décrit l'approche générale, qui peut être adaptée à Entity Framework.

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

pnschofield
la source