根据域模型模式,我们必须对域实体也有行为。我正在使用实体框架进行数据访问。我已经提取了所有实体并将其作为分部类移动到域图层。现在,我在域层中有另一组部分类,其行为与存储库相关。问题是存储库还引用了域模型中的实体,导致循环引用。
任何人都可以为此提供设计解决方案吗?
答案 0 :(得分:1)
用抽象的术语说话很难,所以这里有一个可能有用的例子。想象一下,我们有一项服务可以让Car
去旅行。在此行程中,Car
可能会耗尽气体并需要换油。
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可以整体操纵汽车。汽车负责处理它的内部逻辑,例如消耗汽油和弄脏油。如果坦克中没有足够的气体,也许drive
会返回实际覆盖的距离。如果它不是正常现象,它可能会引发异常。 drive
方法还可以检查汽车是否已启动,是否有油,是否有气体,以及座椅是否有弯曲。启动汽车可能会以不同的速度消耗汽油。您可以看到TripService('应用程序')与CarRepository
对话并操纵Car
,但Car
对CarRepository
一无所知,但仍有逻辑。
处理天然气和石油的变化可能不是TripService
在现实生活中的责任,但在模拟汽车磨损的应用中,它可能会承担这些责任。
要回到抽象术语,您的服务会与存储库和工厂交互以获取域对象。然后,他们在需要的地方协调域对象之间的交互。毕竟,有些东西必须告诉您的域对象该做什么。这就是服务发挥作用的地方。域对象对存储库一无所知,因为它们持久性无知。了解自身的持久性并不会影响业务逻辑,因此您无法在域对象中处理它。他们只处理业务逻辑和维护不变量。存储库必须知道域对象,因为它们会持久存储并检索它们。
答案 1 :(得分:0)
将域层中的部分类与存储库中的行为对话移动到适当的服务中。
您的模型不应该知道有关存储库的任何信息。您的存储库会使用该模型并将其保存到您的数据库中。
然后在模型顶部有一个层,无论是ASP.NET MVC中的WCF服务或控制器,还是位于顶部的控制台应用程序中的Main方法,并组织域模型交互,然后通过存储库持久保存到数据库
您的模型不是放置所有应用程序的地方。