But combining queries and different fetchmodes scenario's will lead to a cartesian product of possibilities if used in a traditional, repository-like way.
For example:
- IList<Author> GetAuthors()
- IList<Author> GetAuthorsWithArticles()
- IList<Author> GetAuthorsWithBooks()
- IList<Author> GetAuthorsWithBooksAndArticles()
- IList<Author> GetAuthorsByLastname(string lastname)
- IList<Author> GetAuthorsByLastnameWithBooks(string lastname)
- etc...
This looks like a bad design.
The solution is the Query Object pattern (here and here). This pattern wraps queries in objects.
If the query is an object, and the fetchmode can also be configured in an object-oriented way, applying fetchprofiles to a query and executing the query looks like this:
// .. get session and transaction somewhere .. var results = new AuthorsByNameQuery() .LastName("Adams") .WithBooks() .WithArticles() .List(session);
The query object wraps the criteria and fetchmode:
class AuthorsByNameQuery { internal DetachedCriteria Criteria; public AuthorsByNameQuery() { Criteria = DetachedCriteria.For<Author>(); } public IList<Author> List(ISession session) { return Criteria .GetExecutableCriteria(session) .List<Author>(); } public AuthorsByNameQuery Lastname(string lastname) { Criteria.Add(Expression.Eq("Lastname", lastname)); return this; } public AuthorsByNameQuery WithBooks() { Criteria.SetFetchMode("Books", FetchMode.Select); return this; } public AuthorsByNameQuery WithArticles() { Criteria.SetFetchMode("Articles", FetchMode.Select); return this; } }
I have been using queries and fetchprofiles this way in a few projects now and it really helps to structure the possibilities.
No comments:
Post a Comment