Efficently loading deep object graphs
Here is an interesting approach to get deep object graphs effectively. This will ensure that you will get all the relevant collections without having to lazy load them and without a huge cartesian product. Especially useful if you want to load a collection of items with the associated deep object graph.
public Policy GetPolicyEagerly(int policyId) { IList list = ActiveRecordUnitOfWorkFactory.CurrentSession.CreateMultiQuery() .Add(@"from Policy policy left join fetch policy.PolicyLeadAssociations
where policy.Id = :policyId") .Add(@"from Policy policy left join fetch policy.PolicyEmployeeAssociations
where policy.Id = :policyId") .Add(@"from Policy policy left join fetch policy.PolicyManagerAssociations
where policy.Id = :policyId") .Add(@"from Policy policy left join fetch policy.PolicyDepartmentAssociations
where policy.Id = :policyId") .Add(@"from Policy policy left join fetch policy.PolicyCustomerAssociations
where policy.Id = :policyId") .SetEntity("policy", Policy) .List(); IList firstResultList = (IList) list[0]; if(firstResultList.Count==0) return null; return = (Policy) firstResultList [0]; }
The domain above is a fake one, by the way, don't try to make any sense of it.
Comments
You mean... there are o/r mappers out there which fetch graphs using cartesian products? :X
Ugh...
I mean, that is one option that you have, yes.
Sorry for my ignorance, but what's the difference with adding "SetFetchMode" ?
IList list = Session.CreateCriteria(typeof (Policy ))
This will return a single result set.
The problem with that is that if you try to load all of that in a single result set, you will have a big Cartesian product.
The approach above uses separate queries, but only a single round trip
Florent, I'm guessing what you wrote would cause the huge cartesian product Ayende mentioned.
Damn, he's just too quick, isn't he ? :-)
Ok, if I understand well, you mean it's faster to do 5 requests with only one join between two tables in each request instead of one big request between the 6 tables ?
BTW, I forgot the .Add(new EqExpression("Id", policyId)) between CreateCritera and the first SetFetchMode for removing the Cartesian product.
@Sven : yeah, damn fast ! ;)
@ Florent,
Yes, that would be faster, but the key part here is that it is 5 request, but a SINGLE round trip
I may be mistaken, but shouldn't the line:
.SetEntity("policy", Policy)
be
.SetInt32("policyId", policyId)
Yes, it should be
I'm wondering what is the Hibernate equivalent syntax for achieving this since there's no CreateMultiQuery() function?
Allen,
That is something that I added to NHibernate, Hibernate has no equivalent that I know of
Comment preview