我有三张牌桌 - Recipient
,Message
,MessageType
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子句?
答案 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"/> & <paramref name="bits"/> > 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);
}