2010-05-10 4 views
3

Comment effectuer une recherche HQL ou Criteria (ce dernier est préférable) impliquant une énumération utilisée comme indicateurs. En d'autres termes, j'ai une propriété enum persistante qui stocke une sorte de drapeaux. Je veux interroger tous les enregistrements qui ont un de ces drapeaux. Utiliser Eq ne fonctionnera bien sûr pas car cela ne sera vrai que si c'est le seul drapeau défini.Comment interroger les indicateurs stockés enum en NHibernate

Résoudre ceci en utilisant l'API Criteria serait le meilleur, mais si cela est seulement faisable en utilisant HQL c'est bien aussi.

Répondre

12

Voici comment vous pourriez le faire avec critères e API:

[Flags] 
enum Bar{ 
    A = 0x01, 
    B = 0x02, 
    C = 0x04 
} 

var criteria = this.Session.CreateCriteria<Foo>() 
      .Add(BitwiseFlags.IsSet("Bar", Bar.A | Bar.C)); 

utilisant:

public class BitwiseFlags : LogicalExpression 
{ 
    private BitwiseFlags(string propertyName, object value, string op) : 
     base(new SimpleExpression(propertyName, value, op), 
     Expression.Sql("?", value, NHibernateUtil.Enum(value.GetType()))) 
    { 
    } 

    protected override string Op 
    { 
     get { return "="; } 
    } 

    public static BitwiseFlags IsSet(string propertyName, Enum flags) 
    { 
     return new BitwiseFlags(propertyName, flags, " & "); 
    } 
} 

devrait générer la sortie suivante where:

FROM _TABLE 
WHERE (this_.Bar & 5 = 5) 

qui devrait vous donner des lignes qui ont des drapeaux et Bar.c bars.Un ensemble (à l'exclusion de tout le reste). Vous devriez être capable de l'utiliser avec conjonction et disjonction aussi.

+1

Comment puis-je faire cela avec QueryOver? – davymartu

+1

Trouvé la solution QueryOver parfaite à https://github.com/AndreasJilvero/NHibernate.Bitwise. Très reconnaissant d'avoir trouvé cela pourrait donc ajouter aux requêtes QueryOver existantes, par opposition à les basculer. Mise en œuvre agréable et propre. – Ted

-2

Vous cherchez Expression.Or si vous interrogez 2 valeurs ou Expression.Disjunction si vous interrogez pour plus de 2 valeurs:

criteria.Add(
    Expression.Disjunction() 
    .Add(Expression.Eq("property", value1)) 
    .Add(Expression.Eq("property", value2)) 
    .Add(Expression.Eq("property", value3)) 
) 
+2

Je ne pense pas que cela fonctionnera avec les énumérations basées sur les drapeaux – SztupY

+0

je vois. bon exemple de la mauvaise réponse alors. –

6

HQL est facile:

var matching = session.CreateQuery(@" 
         from MyEntity 
         where FlagsProperty & :flag = :flag 
         ") 
         .SetParameter("flag", MyEnum.FlagValue) 
         .List<MyEntity>(); 
+0

Existe-t-il un moyen d'obtenir la même chose en utilisant NHibernate LINQ? J'essaye de faire quelque chose comme ceci .... d'obj dans la session.Linq () où (obj.FlagsProperty & indicateur) == (flag) select obj); ... où flag est le paramètre mais qu'il lance une exception "System.NullReferenceException: Référence de l'objet non définie sur une instance d'un objet" – nabeelfarid

+0

Steve vient de répondre à cette question dans le forum, en supprimant ma réponse précédente –

+0

oui c'est ... merci – nabeelfarid

3

Voici comment je résolu en utilisant les critères:

Expression.Eq(
    Projections.SqlProjection("({alias}." + propertyname + " & " + 
    ((int)value).ToString() + ") as " + propertyname + "Result", 
    new[] { propertyname + "Result" }, 
    new IType[] { NHibernateUtil.Int32 } 
), value); 
Questions connexes