【问题标题】:How to query flags stored as enum in NHibernate如何查询在 NHibernate 中存储为枚举的标志
【发布时间】:2011-02-17 20:07:59
【问题描述】:

如何进行涉及用作标志的枚举的 HQL 或 Criteria 搜索(首选后者)。换句话说,我有一个存储某种标志的持久枚举属性。我想查询设置了这些标志之一的所有记录。当然,使用 Eq 是行不通的,因为只有当那是唯一的标志集时才会如此。

使用 Criteria API 解决这个问题是最好的,但如果这只能使用 HQL 也是可行的。

【问题讨论】:

    标签: c# nhibernate criteria enums flags


    【解决方案1】:

    以下是使用条件 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 的行(不包括其他所有内容)。您应该也可以将它与连词和析取词一起使用。

    【讨论】:

    • 我如何使用 QueryOver 做到这一点?
    • github.com/AndreasJilvero/NHibernate.Bitwise 找到了完美的 QueryOver 解决方案。非常感谢发现这样可以添加到现有的 QueryOver 查询而不是切换它们。漂亮而干净的实现。
    【解决方案2】:

    HQL 很简单:

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

    【讨论】:

    • 有没有办法使用 NHibernate LINQ 实现相同的目标?我正在尝试做这样的事情.... from Session.Linq() where (obj.FlagsProperty & flag) == (flag) select obj); ...其中标志是参数,但它抛出异常“System.NullReferenceException:对象引用未设置为对象的实例”
    • 史蒂夫刚刚在论坛里回答了这个,删除了我之前的回复
    • @nabeelfarid 您是否找到了使用 Linq 执行此操作的方法?谢谢。
    【解决方案3】:

    这是我使用 Criteria 解决的方法:

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

    【讨论】:

      【解决方案4】:

      如果您正在查询 2 个值,则您正在寻找 Expression.Or,如果您正在查询超过 2 个值,您正在寻找 Expression.Disjunction

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多