Microsoft Repository Pattern 文档中 IAggregateRoot 接口的用途

Lit*_*nny 3 c# database design-patterns repository-pattern

我正在查看 Microsoft 网站上的 Respository Pattern。

存储库模式

我部分我不明白 IAggregateRoot 做什么?

public interface IRepository<T> where T : IAggregateRoot
    {
        //....
    }
Run Code Online (Sandbox Code Playgroud)

每个存储库类是否可以相互交互,例如 OrderRespository 可以使用 Product 存储库。

Sco*_*nen 10

特尔;博士:

IAggregateRoot除了标记聚合根的类之外,该接口并没有真正做任何事情,以便如果一个类没有实现该接口,

public class Repository<NotARootAggregate> : IRepository<NotARootAggregate>
Run Code Online (Sandbox Code Playgroud)

...不会编译。它帮助我们不要为不是聚合根的类创建存储库。


该通用约束只是一种防止为不是聚合根的东西创建存储库的方法。

什么是聚合根,为什么在我们创建存储库时它很重要?这是一个非常人为的例子:

public interface IAggregateRoot { }

public enum TreeType
{
    Apple, Lemon
}

public class Fruit
{
    public Fruit(TreeType fruitType) { FruitType = fruitType; }

    public TreeType FruitType { get; }
}

public class TreeBranch
{
    private List<Fruit> fruitOnBranch = new List<Fruit>();

    public TreeBranch(TreeType branchType) { BranchType = branchType; }

    public TreeType BranchType { get; }

    public void AddFruit(Fruit fruit)
    {
        if (fruit.FruitType != BranchType)
        {
            throw new ArgumentException("Wrong type of fruit!");
        }
        fruitOnBranch.Add(fruit);
    }
}

public class Tree : IAggregateRoot
{
    private List<TreeBranch> branches = new List<TreeBranch>();

    public Tree(TreeType treeType) { TreeType = treeType; }

    TreeType TreeType { get; }

    public void AddBranch(TreeBranch branch)
    {
        if(branch.BranchType != TreeType)
        {
            throw new ArgumentException("Wrong type of branch!");
        }
        branches.Add(branch);
    }
}
Run Code Online (Sandbox Code Playgroud)

它的设计使得在树上添加错误种类的树枝或在树枝上添加错误种类的水果是不可能的。所以在苹果树上加柠檬是不可能的。把柠檬变成苹果也是不可能的。该代码强制执行正确的水果在正确的树上生长的规则。

将树作为聚合根意味着我们只将树连同它的树枝和果实一起保存到数据库中。我们永远不会只保存树枝或水果。只要我们坚持这样做,我们就不会意外地在苹果树上加柠檬。

如果我们定义了 aFruitRepository那么我们可能会不小心绕过它并保存不正确的水果。

因此,使用该通用约束声明存储库:

public interface IRepository<T> where T : IAggregateRoot
                                ^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

意味着实现接口的类不会编译,除非T实现IAggregateRoot

所以唯一的目的IAggregateRoot是标记一个类并说,“这是一个聚合根。可以为它定义一个存储库。” 这就是您引用的文档将其称为“标记界面”的原因。

这有点奇怪,因为您可以将该界面放在Fruit或 上TreeBranch,然后您就可以为它们创建存储库。没有什么能阻止你这样做。但这个想法是你或其他人会知道不要这样做。(但如果您已经知道不要这样做,那么您就不需要IAggregateRoot界面来阻止您创建存储库,对吗?)