在需要依赖项时,如何/在何处将业务逻辑放入EF实体?

and*_*ree 2 .net architecture domain-driven-design entity-framework dependency-injection

我正在尝试为我的应用编写一些业务逻辑.我的应用程序的核心是来自Database First模型的EF生成实体.我已经从.edmx部分分离了生成的类(.tt文件).

我想找到放置业务逻辑的最佳位置,但问题是,业务逻辑需要一些复杂的依赖关系,例如,需要记录,调用一些WebService,或者对DB进行纯SQL调用.因此,我不能只使用new()内部函数并创建硬依赖项,但我想以某种方式从它们中抽象出来,遵循DI原则.

public class Person
{
    public Person(IDbCaller dbCaller, IWebServiceCaller webServiceCaller) { }
}
Run Code Online (Sandbox Code Playgroud)

我的第一个赌注是使用扩展EF类的部分类.

但在阅读了一些文章后,我现在认为将依赖注入EF类并不是一个好主意:

为什么不使用IoC容器来解析实体/业务对象的依赖关系?

http://lostechies.com/jimmybogard/2010/04/14/injecting-services-into-entities/

那么,我应该把这个逻辑放在哪里呢?我同意,对EF实体的依赖性很差,但我真的找不到解决方案.逻辑需要在某个地方.我看到一些选项/问题:

1)在Service层中放置业务逻辑(需要依赖关系).这可能导致贫血领域模型,但是服务层可能是这种逻辑的正确位置,需要依赖性?

2)创建一些king或Wrapper/Factory类,每次查询返回实体时我都需要调用它,所以我可以用业务逻辑包装实体.

3)将该逻辑放在其他类中,将实体作为函数参数.

对此有哪些好的常见做法?

Jot*_*aBe 7

问题是你混合了两种相反的设计:DDD和贫血模型.

  • DDD:就业务逻辑而言,不存在依赖关系,因为对象本身就是必须实现它的东西
  • 贫血模型:这是使用EF的常用方法.对象是POCO:Fowler说"袋子的属性设置者和吸气剂",并认为它是反模式.所有逻辑都在接收实体的服务中实现,并根据业务规则进行更改

如果你使用DDD

应用程序中的类必须是域对象(实体和值对象).您必须实现它们,而不考虑它们将如何存储在数据库(或您使用的任何后端)中.完成域对象设计后,您将实现一个满足域对象持久性需求的EF模型.因此,在许多情况下,域对象(实体和值对象)与EF实体之间不会直接映射.

即在此实现中,您的域对象必须在某个时刻存储数据.而且您必须实现支持存储此数据的EF模型.

至于依赖关系,在这种情况下,它们将在您的域对象中,而不在您的EF实体中.然后,您可以使用常用模式(Factory,DI)来创建域模型.可能其中一个依赖项是使用EF实现的存储库.

如果你使用贫血模型

首先,我必须说有很多成功的实现,即使Fowler说这是一种反模式.我不会同意或不同意福勒,但我必须暴露事实.

如果使用贫血模型实现应用程序,则可以从设计EF(贫血)模型开始,然后在服务类中实现所有业务逻辑.

这个大错误

贫血模型通常是以数据为中心的设计的结果.用福勒的话说:我不知道为什么这种反模式如此普遍.我怀疑这是因为许多人没有真正使用适当的域模型,特别是如果他们来自数据背景.所以,如果你开始这样做:我的应用程序的核心是来自Database First模型的EF生成实体.你将无法实现纯DDD(你可以阅读这篇文章来理解为什么)

回答你的意见:

1)这是一个贫血模型

2)您期望从存储数据到域对象的直接映射.您收到一个实体并希望为其添加功能.不!您的域对象必须使用EF来请求持久化数据,而不是反过来!

3)这又是1)

你可以发现这篇文章非常有趣:贫血领域模型没有反模式,它是一个固体设计和它的反驳:富域是固体,贫血领域是反模式