Как запросить флаги, хранящиеся как enum в NHibernate - PullRequest
3 голосов
/ 10 мая 2010

Как выполнить поиск HQL или Criteria (последний предпочтителен) с использованием перечисления, которое используется в качестве флагов. Другими словами, у меня есть постоянное свойство enum, которое хранит какие-то флаги. Я хочу запросить все записи, которые имеют один из этих установленных флагов. Использование Eq, конечно, не сработает, потому что это будет только так, если установлен только этот флаг.

Лучше всего решить эту проблему с помощью API Criteria, но если это возможно только с использованием HQL, то это тоже хорошо.

Ответы [ 4 ]

12 голосов
/ 13 мая 2011

Вот как это можно сделать с помощью API критериев:

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

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

с помощью:

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, " & " );
    }
}

должен сгенерировать следующий вывод where:

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

, который должен давать вам строки с установленными флагами Bar.A и Bar.C (исключая все остальное). Вы должны быть в состоянии использовать это также с соединением и дизъюнкцией.

6 голосов
/ 11 мая 2010

HQL это просто:

var matching = session.CreateQuery(@"
                       from MyEntity
                       where FlagsProperty & :flag = :flag
                       ")
                      .SetParameter("flag", MyEnum.FlagValue)
                      .List<MyEntity>();
3 голосов
/ 14 мая 2010

Вот как я решил, используя критерии:

Expression.Eq(
  Projections.SqlProjection("({alias}." + propertyname + " & " + 
    ((int)value).ToString() + ") as " + propertyname + "Result",
    new[] { propertyname + "Result" },
    new IType[] { NHibernateUtil.Int32 }
  ), value );
0 голосов
/ 11 мая 2010

Вы ищете Expression.Or, если запрашиваете 2 значения, или Expression.Disjunction, если запрашиваете более 2 значений:

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