Query Building In The Domain / Service Layers

time to read 2 min | 324 words

Here is an interesting topic. My ideal data access pattern means that there is a single query per controller per request (a request may involve several controllers, though). That is for reading data, obviously, for writing, I will batch the calls if needed. I am making heavy use of the Multi Criteria/Query in order to make this happen.

I have run into a snug with this approach, however. The problem is that some of the services also do data access*. So I may call to the authorization service to supply me with the current user and its customer, and the service will call the DB to find out about this information. I would rather that it would not do that, since that means extra round trips. Now, NHibernate has the idea of a DetachedCriteria, a query that has semi independent life, can be constructed at will and massaged to the right shape anywhere in the code.

Now, I have the following options. Use the normal method:

ICollection<Customer> customers = AuthorizationService.GetAssociatedCustomers();
ICollection<Policy> policies = Repository<Policy>.FindAll(
	Where.Policy.Customer.In(customers)
  );

PropertyBag["customers"] = customers;
PropertyBag["policies"] = policies;

Use DetachedCriteria as a first level building block:

DetachedCriteria customersCriteria = AuthorizationService.GetAssociatedCustomersQuery();
IList results = session.CreateMultiCriteria()
	.Add(customersCriteria)
	.Add(DetachedCriteria.For<Policy>()
		.Add( Subqueries.PropertyIn("id", CriteriaTransformer.Clone(customersCriteria)
.SetProjection(Projections.Id())
) ) ).List(); ICollection<Customer> customers = Collection.ToArray<Customer>(results[0]); ICollection<Policy> policies = Collection.ToArray<Policy>(results[1]); PropertyBag["customers"] = customers; PropertyBag["policies"] = policies;

Remember, I consider Querying a Business Concern, so I like the ability to move the query itself around.

Thoughts?

*  By data access, I mean, they call something that eventually resolves in a DB call.