观看 Jimmy Bogard 的 NDC12 演示“Crafting Wicked Domain Models”后(http://ndcoslo.oktaset.com/Agenda http://ndcoslo.oktaset.com/Agenda),我在想如何持久化这种领域模型。
这是演示中的示例类:
public class Member
{
List<Offer> _offers;
public Member(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
_offers = new List<Offer>();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Offer> AssignedOffers {
get { return _offers; }
}
public int NumberOfOffers { get; private set; }
public Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc)
{
var value = valueCalc.CalculateValue(this, offerType);
var expiration = offerType.CalculateExpiration();
var offer = new Offer(this, offerType, expiration, value);
_offers.Add(offer);
NumberOfOffers++;
return offer;
}
}
所以这个领域模型中包含一些规则:
- 会员必须有名字和姓氏
- 优惠数量无法在外部更改
- 会员负责创建新报价、计算其价值和分配
如果尝试将其映射到某些 ORM(例如 Entity Framework 或 NHibernate),它将无法工作。
那么,使用 ORM 将此类模型映射到数据库的最佳方法是什么?
例如,如果没有setter,如何从数据库加载AssignedOffers?
对我来说唯一有意义的是使用命令/查询架构:查询始终使用 DTO 作为结果,而不是域实体,并且命令是在域模型上完成的。此外,事件溯源非常适合领域模型上的行为。但这种 CQS 架构可能并不适合每个项目,特别是棕地项目。或不?
我知道这里有类似的问题,但找不到具体的例子和解决方案。
这其实是一个非常好的问题,也是我一直在思考的问题。创建完全封装的正确域对象(即没有属性设置器)并使用 ORM 直接构建域对象可能很困难。
根据我的经验,有3种方法可以解决这个问题:
- 正如 Luka 已经提到的,NHibernate 支持映射到私有字段,而不是属性设置器。
- 如果使用 EF(我认为不支持上述内容),您可以使用纪念品图案 http://en.wikipedia.org/wiki/Memento_pattern恢复域对象的状态。例如您使用实体框架来填充域实体接受的“备忘录”对象以设置其私有字段。
- 正如您所指出的,将 CQRS 与事件源结合使用可以消除此问题。这是我制作完美封装的域对象的首选方法,它还具有事件溯源的所有附加优点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)