Non è tantissimo tempo che uso Nhibernate e perciò mi capita spesso di imparare qualcosa di nuovo.
Oggi stavo facendo un po' di fine tuning su un'app windowsforms che è a buon punto. In particolare stavo lavorando sul fetching mode di alcune query.
Il caso era una classica relazione padre figlio (ad es. blogs- blogs item) e volevo caricare tutti i padri e tutti i figli con un'unica select (disabitando il lazy-loading).
Il primo approccio è stato:
IList blogs = session.CreateCriteria(typeof (Blog))
.SetFetchMode("Items", FetchMode.Join)
.List();
Il problema è che se nel db ci sono 2 blog ognuno dei quali ha 3 post la lista caricata dal codice sopra conterrà 6 blog (2x3)! In realtà sono le istanze sono 2 ma vengono duplicate nella collezione per effetto della LEFT JOIN che Hibernate esegue sul database.
Naturalmente non è il comportamento che mi aspettavo, quello che volevo era avere 2 blog con i rispettivi items (3 per ogni blog).
Per ottenere tutto ciò basta specificare una trasformazione sui dati chiamando il metodo SetResultTransformer:
IList blogs = session.CreateCriteria(typeof (Blog))
.SetFetchMode("Items", FetchMode.Join)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List();
La classe NHibernate.Transform.DistinctRootEntityResultTransformer si occupa di trasformare la collezione in modo che contenga solo i 2 blog con i rispettivi items.