纯粹的DDD方法可以与NHibernate一起使用吗?

Mic*_*ock 6 nhibernate asp.net-mvc domain-driven-design repository

我一直在阅读DDD,我很困惑在使用像NHibernate这样的ORM时它会如何适应.

现在我有一个.NET MVC应用程序与相当"胖"的控制器,我正在试图弄清楚如何最好地解决这个问题.将此业务逻辑移动到模型层中是最好的方法,但我不确定如何做到这一点.

我的应用程序已设置好,以便NHibernate的会话由HttpModule管理(获取会话/事务),这是由返回实体对象的存储库使用的(Think S#arp arch ...结果是真的重复了一个很多他们的功能).这些存储库由DataServices使用,它现在只是存储库的包装(它们之间的一对一映射,例如UserDataService采用UserRepository,或实际上是存储库).这些DataServices现在只确保在保存/更新时检查装饰实体类的数据注释.

通过这种方式,我的实体实际上只是数据对象,但不包含任何真实的逻辑.虽然我可以在实体类中放置一些东西(例如"批准"方法),当该操作需要执行诸如发送电子邮件或触摸其他非相关对象之类的操作时,或者,例如,检查是否有任何用户在批准之前拥有相同的电子邮件等,那么实体将需要访问其他存储库等.用IoC注入这些用户不适用于NHibernate,所以你必须使用工厂模式我假设得到这些.我不知道你怎么会在测试中嘲笑那些.

因此,我认为,下一个最合乎逻辑的方法是,每个控制器基本上都有一个服务,并将当前控制器中正在完成的所有工作提取到每个服务的方法中.我认为这可以打破DDD的想法,因为逻辑现在不再包含在实际的模型对象中.

另一种观察方式我认为这些服务中的每一个都与它所使用的数据对象形成一个单一的模型(数据存储区域的分离和对其进行操作的逻辑),但我只是想看看其他什么正在使用像NHIB这样的ORM来解决DDD的"胖控制器"问题,它通过返回填充的数据对象和存储库模型来工作.

更新 我想我的问题是我如何看待这个:NHibernate似乎把业务对象(实体)放在堆栈的底部,然后存储库继续操作.服务器使用存储库,这些服务可以使用多个存储库和其他服务(电子邮件,文件访问)来执行操作.即:应用程序>服务>存储库> Business Objects

我正在阅读的纯DDD方法似乎反映了Active Record偏差,其中CRUD函数存在于业务对象中(我直接调用User.Delete而不是来自服务的Repository.Delete),以及实际的业务对象句柄在这种情况下需要完成的事情的逻辑(如通过电子邮件发送用户,删除属于用户的文件等).即应用程序>(服务)> Business Objects>存储库

使用NHibernate,看起来我会更好地使用NHibernate函数的第一种方法,并且我正在寻找对我的逻辑的确认.或者如果我感到困惑,可以对这种分层方法如何工作进行一些澄清.我的理解是,如果我有一个"批准"方法来更新用户模型,保留它,并且让我们说,给少数人发电子邮件,这个方法应该放在用户实体对象上,但允许适当的IoC,所以我可以注入messagingService,我需要在我的服务层而不是User对象上执行此操作.

从"多UI"的角度来看,这是有道理的,因为执行操作的逻辑是从我的UI层(MVC)中取出的,并放入这些服务中...但我实际上只是将逻辑分解为另一个类而不是直接在控制器中执行它,如果我不会涉及任何其他UI,那么我刚刚交换了一个"胖控制器"用于"胖服务",因为该服务实际上将封装每个控制器动作的方法来完成它的工作.

que*_*rin 4

DDD没有Active Record 倾向。 删除应该是 DDD 中实体(如用户)上的方法。

NHibernate 确实很好地支持 DDD 方法,因为它与实体类完全分离。

当该操作需要执行诸如发送电子邮件或触摸其他不相关对象之类的操作时

您似乎缺少的拼图之一是领域事件。域实体不应直接发送电子邮件。它应该在域中引发一个事件,表明发生了一些重大事件。实现一个类,其目的是在事件发生时发送电子邮件,并注册它来侦听域事件。

或者,例如,在批准之前检查是否有任何用户具有相同的电子邮件地址

这可能应该在提交对“批准”的调用之前进行检查,而不是在执行批准的函数中进行检查。在调用代码中将决策提升一个级别。

因此,我认为下一个最合乎逻辑的方法是为每个控制器提供一个服务

如果您理解服务是客户端的入口点,那么这是可行的。该服务的目的是从前端/客户端获取 DTO 中的参数,并将其转换为针对实体的方法调用,以便执行所需的功能。