I am going through Domain Driven Design by Eric Evans where he outlines the interplay between Repositories and Factories. The repository itself will call an DB interface to get a result set. This result set would then be passed to a factory that would understand that result set to reconstitute the object.
What if the data was hierarchical in nature, like some sort of tree structure. For example:
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
}
Using DDD I would have my interfaces and implementations:
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;
}
}
If I try to build the children in the factory then I need access to the repo again. If I do it in the Repo I feel like I am doing work that should be for the factory. Not sure how to tackle this one.
One thought I had is that the Foo is not the aggregate root but rather 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.
Any help would be very appreciated.
Assuming you need all children when working wit a
Foo
, you should fetch them in the repository and reconstruct the hierarchy in your factory. If you don't necessarily need them; or you might need them in some corner case scenarios, you could consider fetching them lazily, but I assume that this is not what you're after here.When constructing a hierarchy like this, you want to make sure to only hit the database once. For instance, if you'd fetch
Foo foo1
in one call to the db and then fetch the children offoo1
using the same repository methodrepo.Get(foo1.Id)
, then you'd have an additional db roundtrip for each child ... and then some more if you this recursively for each child too. You don't want this, because it would result in an unknown number of additional database round trips (a variant of the select N+1 problem).What you want, is a repository that fetches your complete hierarchy in one database roundtrip. If you are using an ORM, then often the ORM has something build in to handle this for you; for instance NHibernate has a
DistinctRootEntityResultTransformer
to do exactly this.If you want to this with a plain-sql repository, then I'd create a stored procedure (assuming you are using Sql Server) that fetches all
Foo
rows in the hierarchy recursively from the database and returns them in one result set to the repository. The repository then passes this result set to your factory to create the object tree.So the key is not to pass a single
Foo
to your factory, but instead pass areader
to the factory that reads a result set ofFoo
rows, instead of a single row.Update
After re-reading your question, I think you and @enrico are spot on: