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"/> & <paramref name="bits"/> > 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是有界的,您就可以添加额外的消息类型,而不需要任何架构更改。当然,我们可以使用许多链接表来实现同样的效果,但是这种方法更加轻量级。投票以重复方式结束。谢谢:)