a)域实体不应包含与持久性相关的代码,因此它们应该是 Persistence Ignorant PI 。但假设域模型 DM 是使用实体框架设计的,并假设服务层为执行CRUD操作POCO 域实体通过 Linq-to-Entities ,我们认为服务层直接或通过域访问DAL模型:
class CustomerService
{
public string doSomething( ... )
{
...
var customer = context.Customers.Where( ... );
...
}
...
}
b)在 DM 中使用 Linq-to-Entities 是否违反 PI 规则?例如,以下Customer
实体是否违反了PI:
class Customer
{
public string InterestedWhatOtherCustomerOrdered( ... )
{
...
var orders = context.Orders.Where( ... ); // does this violate PI rule?
...
}
...
}
回复Luke McGregor:
A)
是的,因为它直接引用了上下文。一个更好的方法 是使用Customer上的内部导航属性来执行 同样的行动,
那么导航属性应该联系上下文?!但由于导航属性也位于域模型中,我们不能再认为通过直接联系上下文,它们也会违反 PI 吗?
b)根据 Fowler关于Data Mapper的PEAA章节,可以从 Data Mapper 中提取域代码所需的任何方法到接口类中,哪个域然后代码可以使用。如果使用 EF 而不是手写的 Data Mapper ,我们不会违反 PI ?< / p>
谢谢
答案 0 :(得分:3)
是的,因为它直接引用了上下文。更好的方法是使用Customer上的内部导航属性来执行相同的操作,
class Customer
{
public string InterestedWhatOtherCustomerOrdered( ... )
{
...
var orders = this.Orders;
...
}
...
}
或为此函数创建单独的查询类。
答案 1 :(得分:2)
a)DDD中有不同类型的服务。域层服务不应该引用实体框架上下文,因为它会将域与特定的持久性方式紧密耦合 - 与域实体相同,见下文。相比之下,应用程序层服务可以使用上下文(例如调用SaveChanges()
),因为它知道当前的工作单元,何时应该保留。
b)正如Luke所说,是的,它确实违反了PI,因为实体框架上下文是特定于持久性的。在您的实体中,您应该使用持久性无关的方式获取所需的订单。
我不太明白你的InterestedWhatOtherCustomerOrdered()
方法做什么(为什么要返回一个字符串?...)但是你可能有:
class Customer
{
public string InterestedWhatOtherCustomerOrdered( ... )
{
...
var orders = OrderRepository.GetOtherCustomerOrdersByInterest(...);
...
}
...
}
前提是Orders
是聚合根。如果不是,您可以使用域层服务转为基础架构层服务进行查询,或者直接从自己的聚合根中询问订单。