实体框架和避免贫血领域模型


11

在我们的业务逻辑中,我们有时会定义一些类似于以下内容的方法:

User.ResetCourse(Course courseToReset)

问题在于用户和课程都是实体框架代理对象。这意味着当我们在“用户”或“课程”上命中导航属性时,可能会严重打击数据库,因为这些对象不可查询,因此可以正常地遍历它们。

为了解决这个问题,我们将签名更改为:

User.ResetCourse(MyDBContext db, Course courseToReset)

这意味着我们可以直接查询数据库以有效地进行所需的更改,但是将Database上下文传递给业务对象似乎太错误了。

后来我们向用户迁移了服务层,这意味着我们拥有以下内容:

CourseService.ResetForUser(Course courseToReset, User forUser)

该服务引用了创建时注入的DBContext,但是现在我们的业务对象只是没有行为的数据包(例如,Anemic Domain Model)。

我们如何避免这种情况?


11
听起来好像您刚刚意识到实体框架模型实际上是DTO,而根本不是领域模型。您实际上是在尝试DDD吗?如果没有,那可能没关系。
Cochese先生16年

3
ADM plus服务是处理许多事务的良好架构
Ewan


2
@JohnWu是一篇非常有偏见的文章。实际上,通过在丰富示例中包含Active Record模式,它包含丰富域模型的“ Strawman”版本。当然,Active Record不包含在DDD中,并且通常对于任何复杂的应用程序都是一个糟糕的选择。
RibaldEddie '17

Answers:


8

问题是,您首先将EF对象用作域对象。EF对象是数据模型,而不是业务模型。

您需要声明业务对象,这些业务对象使您可以根据需要自由执行操作,然后使用存储库检索和存储它们。您的存储库会将EF实体映射到您的业务实体。决不能在存储库之外使用EF对象。


0

您可以通过执行以下操作来避免这种情况:

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

无论如何,如果您发现我的失误,便会产生某种影响。听起来,您所描述的初始方式所采用的方法与性能有关,而不一定与域的结构有关。因此,实际上您应该考虑解决服务层中的性能问题,但可以将行为保留在域中。如果您想获得更好的答案,那么了解在这种情况下重置用户/课程的含义将很有帮助。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.