聚合根,他们应该负责删除子对象吗?

时间:2013-03-07 07:43:13

标签: 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;set; }

   #endregion

   #region Methods

   public File AddFile(string type, string title, bool share = false)
   {
     ///
   }

   #endregion
}

文件类:

public class File
{
    #region Properties

    public virtual Folder Folder { get; set; }
    public string Title { get; set; }
    public string Type { get; set; }
    public bool Shared { get; set; }

    #endregion

    #region Constructor

    public File(Folder folder, string type, string title, bool share = false)
    {
        ///
    }

    #endregion
}

由于

3 个答案:

答案 0 :(得分:6)

聚合根负责域不变量(请参阅http://dddcommunity.org/library/vernon_2011/)。

所以答案是,聚合根应该是唯一可以访问它聚合的对象的对象。这意味着没有其他对象应该获取对File的引用,并且该File不应该公开任何改变其自身状态的方法。

所有更改子对象状态的方法都应该由聚合根本身公开,因为它必须确保聚合的不变量。

至于持久删除,我通常将域事件建模为.NET事件:然后在返回实体之前由存储库订阅此类事件。因此,在事件处理程序中会出现持久性逻辑(有关详细信息,请参阅http://epic.tesio.it/doc/manual/observable_entities.html

答案 1 :(得分:3)

这在很大程度上取决于您的背景。如果文件具有独立于文件夹的生命周期,则可以将文件设置为实体/ 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; }
}

尝试将其他AR实例的引用保留在AR之外。而且,这种双向关系(File.Folder)不是必需的。这可能表明您正在使用您的域模型进行导航:) ---尽量不这样做。

答案 2 :(得分:3)

AggregateRoots应该负责他们的子对象。对于您的示例,假设文件夹公开了一个Size属性,该属性是根据文件大小的总和确定的。

long Size{get{return Files.Sum(f => f.Size);}

因此,当您实际删除文件时,该文件夹需要了解它。

你现在可能没有Size属性 - 但是跟随DDD的部分目的是当你需要实现它时,它很容易和干净。