I'm learning domain driven design. I am currently trying to write a simply application in C# designing it using DDD. This application has an aggregate root A which can contain 0..n sub entities B. This could be represented with something along the lines of:
class A {
public int Id { get; }
public IList<B> { get; }
}
with a repository:
class ARepository {
public A Get(int id) { ... }
public void SaveOrUpdate(A root) { ... }
public void Delete(A root) { ... }
}
I would however like to add paging when presenting the B sub entities for a given A instance. How would I go about doing that? The best I can come up with is changing A and ARepository to something like:
class A {
public int Id { get; }
}
class ARepository {
public A Get(int id) { ... }
public void SaveOrUpdate(A root) { ... }
public void Delete(A root) { ... }
public IList<B> GetBForA(A root, int offset, int pageSize, out int numPages) { ... }
}
That would work, for sure, but I would loose the simplicity and elegance of the domain model.
What is the best practice for how to handle paging of sub entities with the repository pattern? I'm not looking for how to deal with this using particular libraries, etc. but rather a way to deal with it on the "pattern level".
The short answer is you should not do it like this. Repository purpose is to make accessing domain objects explicit. They should not be used to page data for UI purposes. That's completely different role which I call Finder. Why? You don't want to pollute your domain (repository belongs to domain) with UI concepts like paging. You can find a more detailed explanation here, on my blog.
If you are using an ORM like NHibernate you can achieve this by setting the collection property (IList) lazy loaded, and eagerly fetch the required page or criteria on the object itself instead of the repository. ex:
var a = ARepository.Get(1);
var secondPageOfBs = a.BList.AsQueryable()
.OrderBy(c => c.Name)
.Skip(PageSize * 2)
.Take(PageSize)
.ToList();
you can also build these queries in the repository and get the result in the domain object like:
var a = ARepository.GetWithPagedChildren(1, PageSize * 2, PageSize);
you can also build more complicated eager queries as described: http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With