Domain driven design 聚合根是否应该负责删除子对象?

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

关于聚合根,我有一个问题,它们应该负责删除子对象,还是应该由存储库负责?如果我想通过Id查询一个文件,那么我应该在我的存储库中为此创建一个特定的方法吗

我的聚合根目录的代码段:

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);}