根据域模型模式,我们必须对域实体也有行为。我正在使用实体框架进行数据访问。我已提取所有实体并作为部分类移至域层。现在我在域层中有另一组部分类,其行为与存储库通信。问题是存储库也引用域模型中的实体导致循环引用。
任何人都可以为此提供设计解决方案吗?
根据域模型模式,我们必须对域实体也有行为。我正在使用实体框架进行数据访问。我已提取所有实体并作为部分类移至域层。现在我在域层中有另一组部分类,其行为与存储库通信。问题是存储库也引用域模型中的实体导致循环引用。
任何人都可以为此提供设计解决方案吗?
很难用抽象的术语来谈论,所以这里有一个例子可能会有所帮助。想象一下,我们有一项服务可以让我们Car
旅行。在此行程中,Car
s 可能会用完气,需要换油。
class Car {
private GasTank gasTank;
private OilPan oilPan;
double MPG = 25.0;
void drive( int distance ) {
gasTank.consume( distance / MPG );
oilPan.dirty( distance / OilDirtyRate ); // Making up a term here...but Oil gets dirty
}
void fillUp() {
gasTank.fillUp();
}
void changeOil() {
oilPan.empty();
oilPan.add( new Oil() );
}
}
// These are value objects, there's no identity here
class GasTank { } // Imagine above methods defined
class OilPan { } // more methods
class CarRepository {
Car findByVIN( String vin ) {
// Search Car collection or database
return car;
}
boolean register( Car car ) {
carDao.insert( car.toDTO() );
}
boolean update( Car car ) {
// write to persistence, etc.
}
}
class TripService {
private CarRepository carRepo;
void takeTrip( String carVin, int milesToGo ) {
Car car = carRepo.findByVIN( carVin );
// calculate distance
while ( milesToGo > 0 ) {
car.drive( 200 );
milesToGo -= 200;
if ( car.isOutOfGas() ) {
car.fillUp();
}
if ( car.needsOilChange() ) {
car.changeOil();
}
}
carRepo.update( car );
}
}
我很抱歉使用了另一个汽车示例(和 Java,因为您说的是 C#),但是您可以看到 Car 仍然具有逻辑,但是 TripService 可以将 Car 作为一个整体进行操作。Car 负责处理它的内部逻辑,例如消耗气体和弄脏油。drive
如果油箱中没有足够的气体,可能会返回实际覆盖的距离。如果不是正常发生,它可能会引发异常。该drive
方法还可以检查汽车是否已启动、是否有油、是否有气以及是否扣好座椅节拍。启动汽车可能会以不同的速度消耗汽油。您可以看到 TripService(“应用程序”)与 对话CarRepository
和操作Car
,但对 却Car
一无所知CarRepository
,但仍有逻辑。
处理汽油和机油的更换可能不是TripService
现实生活中的责任,但在模拟汽车磨损的应用程序中,它可能会承担这些责任。
回到抽象术语,您的服务与存储库和工厂交互以获取域对象。然后他们在需要的地方编排域对象之间的交互。毕竟,有些东西必须告诉您的域对象该做什么。这就是服务发挥作用的地方。域对象对存储库一无所知,因为它们是持久性无知的。知道自己是如何持久化的不会影响业务逻辑,因此您无需在域对象中处理它。他们只处理业务逻辑和维护不变量。存储库必须了解域对象,因为它们正在持久化和检索它们。
将具有与存储库对话的行为的域层中的部分类移动到适当的服务中。
您的模型不应该对存储库有任何了解。您的存储库获取模型并将其保存到您的数据库中。
然后,您在模型之上有一个层,无论是 ASP.NET MVC 中的 WCF 服务或控制器,还是位于顶部的控制台应用程序中的 Main 方法,它组织域模型交互,然后通过存储库持久保存到数据库。
您的模型不是放置所有应用程序的地方。