(这可能是重复的,但是在我阅读的其他问题中,我没有找到满意的答案。)
我需要一些有关如何将聚合根的子实体的删除传播到数据库层的指导。我已经/读到了几种不同的处理方式:
保留移走的孩子,我分开收集。让存储库在保存时删除集合中的所有项目。
直接调用某种数据映射层或存储库。
执行某种类型的委托/事件,存储库/ UoW可以提供/监听。
没做什么。让工作单元或存储库将整个聚合根与“非脏”副本进行比较。
值得注意的是,我真正的聚合根实现包含可能被删除的多个子级集合。
为了清楚起见,这是一个简单的示例:
public class AggregateRoot
{
private List<ChildEntity> _children;
public IEnumerable<ChildEntity> Children
{
get
{
return _children;
}
}
public void RemoveChild(ChildEntity child)
{
_children.Remove(child);
// What to do here?
// Option 1: Keep removed children i separate collection. Let
// the repository remove them on save.
RemovedChildren.Add(child);
// Option 2: Call some kind of data mapping layer or repository directly
_childRepository.Delete(child);
// Option 3: Execute some type of delegate/event that a repository
// may provide/listen to.
_onChildRemoved(this, child);
// Option 4: Do nothing. Let the Unit of work or repository compare
// the whole aggregate root with a "non-dirty" copy.
}
}
我认为选项1和2不太优雅。
选项4很不错,因为我不必在聚合根内部施加任何逻辑,但是由于我的实际实现量很大,因此我必须比较很多属性和集合。
我倾向于选择选项3。它的问题在于,它可能需要大量的委托/事件。也许我可以实现一个通用的委托/事件。
这肯定是一个相当普遍的问题,但是我很少见到这样的例子。您将如何处理这个问题?
选项1:我猜您的业务中没有诸如RemovedChildren这样的概念,因此在我看来,聚合不应包含此类集合。请注意,有时可能会有诸如儿童历史,历史儿童之类的概念
选项2:我已经读过很多次了,聚合不应该使用存储库,并且聚合不应该注入任何服务。但是,您可以使用双调度模式并提供方法签名,例如:
public void RemoveChild(ChildEntity child, IChildRepository repository)
{
// check conditions, business logic etc
// remove using repository
但是,它迫使调用者提供存储库,这在某些情况下可能难以实现
选项3:我以前没有为此目的使用过事件。但是对我来说似乎还可以。您可以使用事件总线来通知感兴趣的存储库有关实体删除的信息。
选项4:我认为这是最好的方法,UoW应该处理项目删除。您可以通过在实体上设置某种标志或将其ParentId设置为0(即EF在幕后所做的事情)来将您的实体标记为已删除。提交后,您可以检查所有加载到内存中的对象,并删除标记为删除的对象。这迫使我们在域层中编写最少的基础结构代码,但是我们需要在UoW中编写其他代码以删除孤立的子级。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句