Multiple bag with Fetch'join' in nhibernate

Suppose you have an entity like this

image

your NickName class has two bags, one containing a list of DomainRegistrations, and the other containing a series of Attachments. Now suppose you map both of these with fetch=join, this can cause a really really really big problem.

As you can read in this bug in NHibernate jira, you should know that fetch join is not supported when there is more than one bag in the entity, because bag allows for duplicate items :). When you do your unit testing of the basic mapping functionality (you should always unit test mappings”) when you save a NickName with 2 domains and 2 attachments and reload it, the ISession will give you a nasty object with 4 Domains and 4 Attachments :). If you think that NH should support this scenario think that bag allows duplicate, and this makes impossible for NH to understand from the resultset with fetch join, if the original object has 1 2 3 or 4 attachments.

The obvious solution is to change the fetch mode from join to select, but if you really want to be able to do a fetch=join you can consider if you really want to allow duplicates in your DomainRegistrations and Attachments properties. Mapping association from one to many with a bag is simple, because you can use an IList<T> interface in your domain classes. If you do not want to allow duplicates, and map the collection as a <set> instead of a <bag> you cannot use anymore the IList<T> interface. This is due to the fact that NHibernate rehydrate entities using a specific class that supports set semantic, not allowing a duplicate and it does not implement IList<T>.

In my situation, I can change those two properties from IList<T> to ICollection<T> and initialize them with HashSet<T> framework class. Now I’m able to map them with <set>, setting fetch mode to join avoiding the aforementioned duplicate problem. In the end I would prefer nhibernate to give me an error during mapping compile phase, something telling me you cannot use fetch mode join on a bag when more than a bag is present in an entity, instead of having strange behavior at runtime :)

alk.

Tags: NHibernate