DDD:一个存储库可以访问另一个存储库吗?

Avr*_*amL 7 .net c# domain-driven-design

我对 DDD 很陌生。我已经检查了以下回复:一个存储库可以通过 DDD 访问另一个存储库吗? 之前询问过,但没有找到相关信息。

在我的应用程序中,我有一个对象,其中包含另一个对象作为属性。我有一个主对象的存储库,但为了检索属性的值,需要访问另一个存储库。

我的问题是:第一个存储库应该访问第二个存储库,还是应用程序应该调用两个存储库并将它们合并?

例如:

对于两个类:

public class Foo1
{
    public int Id { get; set; }

    // .... More data

    public Foo2 foo2 { get; set; }
}

public class Foo2
{
    public int Id { get; set; }

    public int Type { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

代码应该是这样的:

public class Foo1Repository
{
    public Foo1 Get() { 
        return new Foo1();
    }
}

public class Foo2Repository
{
    public Foo2 Get(int foo1Id)
    {
        return new Foo2();
    }
}

public class Application
{
    public void main()
    {
        Foo1 foo1 = new Foo1Repository().Get();
        foo1.foo2 = new Foo2Repository().Get(foo1.Id);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者更像:

public class Foo1Repository
{
    public Foo1 Get() {
        Foo2Repository foo2Repository = new Foo2Repository();
        Foo1 foo1 = new Foo1();
        foo1.foo2 = foo2Repository.Get(foo1.Id);

        return foo1;
    }
}

public class Foo2Repository
{
    public Foo2 Get(int foo1Id)
    {
        return new Foo2();
    }
}

public class Application
{
    public void main()
    {
        Foo1 foo1 = new Foo1Repository().Get();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,我很想知道是否有更好的架构?

谢谢!

Far*_*sim 7

DDD 建议专门建立一个存储库来检索和存储一个聚合根;聚合根是在该领域中具有突出作用的实体。实体的修改必须通过聚合根进行:检索聚合根及其存储库,进行必要的修改,然后将其存储回来。聚合根的组成实体不得独立检索和修改,因此没有它们的存储库。

在您的情况下,根据上下文,Foo1似乎是聚合根。只有一个存储库就Foo1足够了;存储库Foo2是多余的。检索实例后,您可以而且必须通过, 修改 的Foo1属性。不得独立检索和修改,从而消除了对存储库的需要。Foo2Foo1Foo1Foo2Foo2

但是,再次取决于上下文,如果您发现Foo2本身就是一个聚合根,那么Foo1它就应该拥有自己的存储库。但是,在这种情况下,Foo1不得在事务中保存对Foo2(即对另一个聚合根的直接引用,这是不建议的)的引用并对其进行修改。Foo2相反,它必须仅通过其标识符进行引用,如下所示:

public class Foo1
{
    public int Id { get; set; }

    // .... More data

    public int foo2Id { get; set; } // Foo2 identfier only, not a Foo2 instance
}

public class Foo2
{
    public int Id { get; set; }

    public int Type { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如果 的修改Foo1需要对 进行相同的修改,则必须通过检索所持有的标识符Foo2来完成,如以下示例所示。请注意,为简单起见,该示例修改了同一事务中的两个聚合根。然而,这种修改通常发生在最终一致的单独事务中。Foo2Foo1

Foo1 foo1 = foo1Repository.findById(foo1Id);

// modify foo1 state

Foo2 foo2 = foo2Repository.findById(foo1.foo2Id);

// modify foo2 state

// persist changes
foo1Repository.store(foo1);
foo2Repository.store(foo2);
Run Code Online (Sandbox Code Playgroud)