Domain driven design 聚合根是否应该负责删除子对象?
关于聚合根,我有一个问题,它们应该负责删除子对象,还是应该由存储库负责?如果我想通过Id查询一个文件,那么我应该在我的存储库中为此创建一个特定的方法吗 我的聚合根目录的代码段:Domain driven design 聚合根是否应该负责删除子对象?,domain-driven-design,ddd-repositories,aggregateroot,Domain Driven Design,Ddd Repositories,Aggregateroot,关于聚合根,我有一个问题,它们应该负责删除子对象,还是应该由存储库负责?如果我想通过Id查询一个文件,那么我应该在我的存储库中为此创建一个特定的方法吗 我的聚合根目录的代码段: public class Folder { #region Properties public Guid Id { get;set; } public Name { get;set; } public virtual ICollection<File> Files { get;se
public class Folder {
#region Properties
public Guid Id { get;set; }
public Name { get;set; }
public virtual ICollection<File> Files { get;set; }
#endregion
#region Methods
public File AddFile(string type, string title, bool share = false)
{
///
}
#endregion
}
感谢聚合根负责域不变量(请参阅) 因此答案是是,聚合根应该是唯一可以访问它聚合的对象的对象。这意味着其他对象不应获取对文件的引用,并且该文件不应公开任何更改其自身状态的方法 所有改变子对象状态的方法都应该由聚合根本身公开,因为它必须确保聚合不变量
至于持久化删除,我通常将域事件建模为.NET事件:这样的事件在返回实体之前由存储库订阅。因此,在事件处理程序中会出现持久性逻辑(有关详细信息,请参阅)这在很大程度上取决于您的上下文。如果文件具有独立于文件夹的生命周期,则可以将文件设置为实体/AR。但是,这意味着您需要断开文件夹中的实例聚合关系,使其仅具有对文件的引用。大概是这样的:
public class Folder
{
public Guid Id { get;set; }
public string Name { get;set; }
public List<ContainedFile> Files { get;set; }
}
public class File
{
public Guid Id { get;set; }
public string Title { get;set; }
}
public class ContainedFile // or FolderFIle or whatever makes sense in your domain
{
public Guid FileId { get;set; }
}
公共类文件夹
{
公共Guid Id{get;set;}
公共字符串名称{get;set;}
公共列表文件{get;set;}
}
公共类文件
{
公共Guid Id{get;set;}
公共字符串标题{get;set;}
}
public类包含file//或FolderFIle或域中有意义的任何内容
{
公共Guid文件ID{get;set;}
}
尝试将对其他AR实例的引用排除在AR之外。此外,这种双向关系(
File.Folder
)也不是必需的。这可能表明您正在使用域模型进行导航:)---请不要这样做。聚合对象应负责其子对象。在本例中,假设文件夹公开了一个Size属性,该属性由文件大小之和决定
long Size{get{return Files.Sum(f => f.Size);}
因此,当您实际删除文件时,文件夹需要知道它
您现在可能没有Size属性,但遵循DDD的部分目的是,当您需要实现它时,它很容易实现。您可以分享一个在聚合根中使用事件的示例吗?这里有一个玩具示例:(但它实际上是一个玩具示例)。不幸的是,我无法共享来自我们域的代码,因为我没有版权。我可以描述一下。例如,AdvisoryContract公开域事件,如RequiringUpdateFassetAllocationForInvestmentsInDraft、CustomizedAssetAllocationForInvestmentsInDraft等,每个事件都在其特定的事件参数中包含有用的信息。这被证明是非常有效的。重申聚合的职责是生成事件,这是一个很好的观点。由服务上下文来处理这些事件。
long Size{get{return Files.Sum(f => f.Size);}