我刚开始想出DDD。贫困领域模型(我学到的实际上只不过是持久性模型)并将逻辑推入视图模型中并不是在削减它。因此,我已经建模了一个更复杂的背景(饲料营养/价格优化器)。我完全认识到DDD实体具有私有设置器并暴露只读集合的事实,并且改变它们的唯一方法是调用实体上的方法。非常容易测试,难以滥用。
这是我的问题。将这个东西保存到数据库是很简单的。对我来说不明显的是如何在不破坏封装的情况下再次实现它。
我一直在使用Entity Framework来加载数据模型。我知道它能够使用域实体&#39;私人制定者,但是:1)反思的魔力可能会误导理性。 2)我绝对不想尝试跳过数据模型并强迫域模型尝试与EF一起玩。 3)数据库的规范化程度略低于域模型。 4)我不认为EF与IReadOnlyList<>
合作得很好。
我还尝试重构和重放方法调用,这会导致实体处于等效状态,但这似乎是不必要的复杂性。对我来说,代码是否正确并不明显。此方法也会引发相当多的线性规划求解和滞后。
为了保持域实体的清洁,我能想到的最后一种方法是在每个名为Materialize
的实体上使用内部静态工厂方法,它接收字段作为参数并返回实体的新实例。存储库应该是唯一访问它的存储库。这是一个好的解决方案吗?我还应该考虑什么?
编辑:我没有实现已保存的状态,而是让我的存储库模拟事件源(重放方法)。我喜欢这个方向。数据库不是事件源,但可以随时轻松切换,因为存储库隐藏了这个。
答案 0 :(得分:3)
基本上你想要使用坚固但很无聊并且维护成本高的Memento图案。很高兴您已经意识到直接与EF实体合作(无论POCO如何)是一个问题,但是有一个简单的解决方案。
将您的EF POCO严格视为DTO,以便从db读取/写入。如果您正确使用Repository pattern,那么您可以将您的聚合根源(手动或使用自动播放器)映射到存储库中
应用程序的其余部分对EF没有任何了解,只有您的回购将充当转换器&#39;从域对象到一个或多个EF POCO并返回。为了将数据导入Domain对象,您可以定义“只读”对象。像
这样的属性 List<string> _data=new List<string>();
public IEnumerable<string> Data
{
get{ return _data;}
private set{
_data=value.ToList();
}
}
这将允许像automapper这样的工具填充对象状态。请注意,该对象仍然是封装的,但私有的setter也可以充当数据&#39; importers&#39;。
就我个人而言,我使用这种方法但没有EF,因此更喜欢json对象并将其存储。 Ofc,该表具有查询所需的列,但是Data
列保存了可以轻松恢复的对象状态。只要您的聚合设计得当,它就可以很好地工作。