2009-06-26 9 views
0

J'essaie de filtrer par une liste de valeurs en utilisant l'API de critères. Je soupçonne que ce n'est pas possible, je demande juste d'être sûr.NHibernate: Filtrage des requêtes sur une liste de valeurs en utilisant les critères

class Entity 
{ 
    int id { get; set; } 
    IList<Guid> Guids { get; set; } 
} 

La mise en correspondance:

<class name="Entity"> 
    <id ...></id> 
    <bag name="Guids" table="Entity_Guids"> 
    <key column="Entity_FK"/> 
    <element column="Guid"/> 
    </bag> 
</class> 

J'ai présumé liste des Guids (en fait ceux-ci est un autre sous-requête). Je veux filtrer toutes les Entités où au moins un guid est dans la liste des Guids.

Sql ressemblerait à ceci:

SELECT * 
FROM Entity e 
    inner join Entity_Guids eg 
    on e.id = eg.Entity_FK 
WHERE 
    eg.Guid in (subquery) 

Avec API critères, cela semble être impossible.

ICriteria query = session 
    .CreateCriteria(typeof(Entity), "e") 
    .Add(Subqueries.In("e.Guids", subquery)) 

Lève une exception.

+0

l'exception? – MatthieuGD

+0

et la sous-requête est un critère détaché? – MatthieuGD

+0

Oui, la sous-requête est un DetachedCriteria. L'exception est que l'argument 'clé' ne doit pas être nul. Il semble être une exception lors de l'accès à un dictionnaire et ne signifie pas beaucoup. –

Répondre

1

Votre requête ne fonctionnera pas car la propriété e.Guids transmise à la sous-requête n'est pas une valeur unique. Pour ce faire, vous essayez d'effectuer une intersection et de vérifier que cette intersection n'est pas vide, ce qui n'existe malheureusement pas dans l'API des critères, bien que vous puissiez probablement le faire avec Linq.

Vous pourriez probablement faire encore cela si vos Guids étaient des entités avec les propriétés appropriées (la propriété Value contient la Guid réelle) et il y avait une relation bidirectionnelle:

var subquery2 = DetachedCriteria.For<GuidEntity>() 
    .Add(Subqueries.In("Value", subquery)) 
    .SetProjection("Entity_FK"); 

ICriteria query = session.CreateCriteria(typeof (Entity)) 
    .Add(Subqueries.In("Id", subquery2)); 
+0

Je pense que pour un comportement correct, vous devez utiliser la méthode Subqueries.PropertyIn() qui utilise "Id" comme colonne de table (ex: eg.Id dans (select ...)). Subqueries.In() vérifie "Id" comme constante (ex: 'Id' dans (select ...). –

Questions connexes