Qualche giorno fa ho cominciato a litigare con una Query, basata su ICriteria, che a dire il vero penso sia una di quelle standard.

Partiamo dal Domain, un Domain più che "conosciuto"

Utenti -> 1:n <- Gruppi

I mapping sono stati scritti in modo che, sebbene nel modello fisico DB ci sia una tabella di relazione che lega le due entità in modo da dare la possibilità di "legare" a un utente più gruppi, siano presenti solo le entità principali, e quindi non la tabella di relazione (che come qualcuno insegna non fa parte del dominio :) ).

User.hbm.xml
<class name="User" table="Users" lazy="true">
<id name="UserId" column="UserId" type="int">
<generator class="native" />
</id>
<bag name="Roles" table="user_role" lazy="true">
<key column="UserId"/>
<many-to-many class="Roles" column="RoleId" />
</bag>
...
</class>
Roles.hbm.xml 
<class name="Roles" table="Roles" lazy="true">
<id name="RoleId" column="RoleId" type="int">
<generator class="native"/>
</id>
<property name="Descrizione" column="Descrizione" type="string"/>
...
</class>

Dopo qualche ora di google, newsgroup e testate sul muro sono arrivato alla conclusione che dovrei forse cominciare a leggermi seriamente il manuale di Nhibernate in quanto facevo un errore veramente DA stupido.

Soluzione che non funzionava (e non capivo il perché):

DetachedCriteria roles = DetachedCriteria.For<RolesU>();
roles.Add(Expression.Or(Expression.Eq("Ruolo", "Admins"),
Expression.Eq("Ruolo", "Sel")));
roles.SetProjection(Projections.Distinct(Projections.Property("IdRole")));

ICriteria criteria = session.CreateCriteria(typeof(Utente));
criteria.Add(Subqueries.PropertyIn("Ruoli", roles));
criteria.AddOrder(Order.Asc("Cognome"));

 

Peccato che pensassi che aggiungere una Subqueris.ProperyIn su una collection e una detached criteria che estrasse collection di oggetti dello stesso tipo facesse automaticamente il confronto e che quindi filtrasse i risultati in tal senso.

Ma ecco la soluzione corretta:

DetachedCriteria roles = DetachedCriteria.For<RolesU>();
roles.Add(Expression.Or(Expression.Eq("Ruolo", "Admins"),
Expression.Eq("Ruolo", "Sel")));
roles.SetProjection(Projections.Distinct(Projections.Property("IdRole")));

ICriteria criteria = session.CreateCriteria(typeof(Utente));
criteria.CreateCriteria("Ruoli").Add(Subqueries.PropertyIn("IdRole", roles));
criteria.AddOrder(Order.Asc("Cognome"));

Insomma mi ero perso completamente il concetto di CreateCriteria (o createAlias come suggerito da Gianmaria Ricci che qui saluto e ringrazio).

Technorati Tags: ,,