c# – 存储库,工厂和分层结构的数据

我正在通过Eric Evans的域驱动设计,他概述了存储库和工厂之间的相互作用.存储库本身将调用DB接口来获取结果集.然后将这个结果集传递给一个工厂,这个工厂将会理解这个结果集来重组对象.

如果数据本质上是分层的,就像某种树结构一样.例如:

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Foo Parent { get; set; }
    public ICollection<Foo> { get; set; }

    // Other business like methods here

}

使用DDD我将有我的接口和实现:

public interface IFooRepository
{
    Foo Get(int id);
}

public interface IFooFactory<TSource>
{
    Foo Create(TSource source);
}

public class sqlFooRepository: IFooRepository
{
    private readonly IFooDao dao;
    private readonly IFooFactory<sqlDataReader> factory;

    public sqlFooRepository(IFooDao dao,IFooFactory factory)
    {
        this.dao = dao;
        this.factory = factory;
    }

    public Foo Get(int id)
    {
        var resultSet = dao.Find(id);
        return factory.Create(resultSet);
    }
}

public class sqlFooFactory: IFooFactory<sqlDataReader>
{
    public Foo Get(sqlDataReader reader)
    {
        var foo = new Foo();
        foo.Id = (int) reader["id];
        foo.Name = (string) reader["name"];
            // Do I build the children accounts here
        return foo;
    }
}

如果我试图在工厂里修建孩子,那么我需要再次访问这个回购站.如果我在回购中做到这一点,我觉得我正在做工作,应该是工厂.不知道如何解决这个问题.

一个想法是,Foo不是聚合根,而是FooTree是总根.所以试图获得任何Foo,我需要创建整个树,这意味着我可以将Foo对象的集合传递到FooTreeFactory.

任何帮助将非常感激.

解决方法

假设您在Foo工作时需要所有的孩子,您应该在存储库中获取它们,并重建工厂中的层次结构.如果你不一定需要他们;或者您可能需要在某些情况下使用它们,您可以考虑轻松抓取它们,但我认为这不是您在此之后.

当构建这样的层次结构时,您需要确保只打数据库一次.例如,如果您在一次调用db中获取Foo foo1,然后使用相同的存储库方法repo.Get(foo1.Id)获取foo1的子项,那么您将为每个子级添加一个额外的db往返. ..然后一些更多,如果你递归地为每个孩子也.您不希望这样做,因为这将导致未知数量的额外的数据库往返(select N+1 problem的变体).

你想要的是一个一个数据库往返中获取完整层次结构的存储库.如果您正在使用ORM,那么通常ORM有一些内置的东西来处理这个;例如NHibernate has a DistinctRootEntityResultTransformer这样做.

如果要使用plain-sql存储库,那么我将创建一个存储过程(假设您正在使用sql Server)从数据库中循环获取层次结构中的所有Foo行,并将它们返回到存储库.存储库然后将此结果集传递到工厂以创建对象树.

所以关键是不要将单个Foo传递给您的工厂,而是将阅读器传递给读取Foo行结果集的工厂,而不是单行.

更新

重读了你的问题后,我想你和@enrico都是:

[…] the FooTree is the aggregate root. So trying to get any Foo I would
need to create the entire tree,which means I Could pass a collection
of Foo objects to a FooTreeFactory

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...