Sql server 如何使用NHibernate';s标准API

Sql server 如何使用NHibernate';s标准API,sql-server,nhibernate,bit-fields,nhibernate-criteria,Sql Server,Nhibernate,Bit Fields,Nhibernate Criteria,可能重复: 我有三个表-Recipient,Message,MessageType MessageType如下所示: | ID | Description | |====|==============| | 1 | JobAlert | | 2 | Newsletter | | 3 | SpecialOffer | | 4 | Survey | Recipient包含一个用作位字段的整数列;收件人可以选择他们想要接收的邮件类型;如果收件人希望接收时事通讯和特

可能重复:

我有三个表-
Recipient
Message
MessageType

MessageType如下所示:

| ID | Description  |
|====|==============|
|  1 | JobAlert     |
|  2 | Newsletter   |
|  3 | SpecialOffer |
|  4 | Survey       |
Recipient
包含一个用作位字段的整数列;收件人可以选择他们想要接收的邮件类型;如果收件人希望接收时事通讯和特别优惠,我们会将其位字段设置为
(2^2)|(2^3)

Message
包含对
MessageTypeId
的引用,以及定义为
POWER(2,MessageTypeId)

我用SQL表示的查询类似于:

SELECT * FROM Message, Recipient
  WHERE Recipient.MessageTypeBitField & Message.MessageTypeBitFlag > 0
通过在bitfield和bitflag列上执行按位AND,可以轻松地仅选择特定收件人感兴趣的邮件

问题是,我不是在SQL中这样做的——我需要将其作为附加选项添加到基于NHibernate Criteria API构建的相当丰富的系统中


有没有办法通过NHibernate API来表达这个标准?或者使用API,或者在现有的标准中添加SQL/HQL子句?

好的,这里有一个基于提交人的具体实现,因为我必须对其进行一些调整以使其正常工作:

/// <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, " & ");
    }
}
///一种NHibernate标准,它执行逐位比较以将位标志与位掩码匹配。
公共类位掩码:LogicalExpression{
专用位掩码(字符串属性名称、对象值、字符串op):
base(新的SimpleExpression(propertyName,value,op),Expression.Sql(“?”,0,NHibernateUtil.Int64)){
}
受保护重写字符串操作{
获取{return“>”;}
}
///创建一个按位过滤标准-即,如果
和&0
公共静态位掩码匹配(字符串属性名称,长位){ 返回新的位掩码(propertyName,位“&”); } }
然后通过Criteria API使用它,如下所示:

public IEnumerable<Message> GetMessagesForRecipient(Recipient r) {
    var messages = session.CreateCriteria<Message>()
        .Add(BitMask.Matches("MessageTypeBitFlag ", r.MessageTypeBitField))
        .List<Message>();
    return(messages);
}
public IEnumerable GetMessagesForRecipient(收件人r){
var messages=session.CreateCriteria()
.Add(BitMask.Matches(“MessageTypeBitFlag”,r.MessageTypeBitField))
.List();
返回(消息);
}

我知道这与您的问题完全正交,所以请随意忽略。您真的需要使用位标志吗?显然,为不同的类型创建单独的列可以解决您的ORM问题,而在DB端,这两种方式的磁盘存储量都是相同的。您可以在biz对象上公开一个合成字段,因此,如果对象的用户想要读/写bitflag变量,那么您只需在幕后将其转换为SQL字段。我认为它使您的模型更容易理解,而不必记住位7代表什么。使用位字段的最大优点是,只要您的ID是有界的,您就可以添加额外的消息类型,而不需要任何架构更改。当然,我们可以使用许多链接表来实现同样的效果,但是这种方法更加轻量级。投票以重复方式结束。谢谢:)