如何使用Hibernate Criteria API指定位掩码/位字段WHERE子句

时间:2012-02-16 02:30:35

标签: sql-server nhibernate bit-fields nhibernate-criteria

  

可能重复:
  How to query flags stored as enum in NHibernate

我有三张牌桌 - RecipientMessageMessageType

MessageType如下所示:

| ID | Description  |
|====|==============|
|  1 | JobAlert     |
|  2 | Newsletter   |
|  3 | SpecialOffer |
|  4 | Survey       |

Recipient包含一个整数列,用作位域;收件人可以选择他们想要接收的消息类型;如果收件人想要收到简报和特别优惠,我们会将其位域设置为(2 ^ 2) | (2 ^ 3)

Message包含对MessageTypeId的引用,以及计算列MessageTypeBitFlag,其定义为POWER(2, MessageTypeId)

我在SQL中表达的查询类似于:

SELECT * FROM Message, Recipient
  WHERE Recipient.MessageTypeBitField & Message.MessageTypeBitFlag > 0

通过在位域和位标志列上执行按位与运算,可以轻松选择特定收件人感兴趣的邮件。

问题是,我不是在SQL中执行此操作 - 我需要将此添加为基于NHibernate Criteria API构建的相当丰富的系统的附加选项。

有没有办法通过NHibernate API表达这个标准 - 使用API​​还是在现有标准中添加SQL / HQL子句?

1 个答案:

答案 0 :(得分:0)

好的,这是基于this linked post提交的Firo的具体实施,因为我必须稍微调整一下以使其有效:

/// <summary>An NHibernate criterion that does bitwise comparison to match a bit flag against a bitmask.</summary>
public class BitMask : LogicalExpression {
    private BitMask(string propertyName, object value, string op) :
        base(new SimpleExpression(propertyName, value, op), Expression.Sql("?", 0, NHibernateUtil.Int64)) {
    }

    protected override string Op {
        get { return ">"; }
    }
    /// <summary>Create a bitwise filter criterion - i.e. one that will be satisified if <code><paramref name="propertyName"/> &amp; <paramref name="bits"/> &gt; 0</code></summary>
    public static BitMask Matches(string propertyName, long bits) {
        return new BitMask(propertyName, bits, " & ");
    }
}

然后通过Criteria API使用它,如下所示:

public IEnumerable<Message> GetMessagesForRecipient(Recipient r) {
    var messages = session.CreateCriteria<Message>()
        .Add(BitMask.Matches("MessageTypeBitFlag ", r.MessageTypeBitField))
        .List<Message>();
    return(messages);
}