.net 如何在Linq to Entities查询中使用标志枚举?
我有这样一个[Flags]枚举:.net 如何在Linq to Entities查询中使用标志枚举?,.net,linq,enums,flags,.net,Linq,Enums,Flags,我有这样一个[Flags]枚举: [Flags] public enum Status { None = 0, Active = 1, Inactive = 2, Unknown = 4 } byte status = (byte)(Status.Active | Status.Unknown); var result = from r in db.Records select r where (r.Status &
[Flags]
public enum Status
{
None = 0,
Active = 1,
Inactive = 2,
Unknown = 4
}
byte status = (byte)(Status.Active | Status.Unknown);
var result = from r in db.Records
select r
where (r.Status & status) != 0
Status s = Status.Active | Status.Unknown;
var result = from r in db.Records
where (s & r.Status) == r.Status
select r
状态枚举可以包含两个值,例如:
Status s = Status.Active | Status.Unknown;
现在我需要创建一个linq查询(linq到ADO.NET实体)并请求状态为s以上的记录,即活动或未知的记录
var result = from r in db.Records
select r
where (r.Status & (byte)s) == r.Status
当然,我会得到一个错误,因为LINQtoEntities只知道在Where子句中处理基元类型
错误是:
无法创建的常量值
类型“闭包类型”。只有原始的
类型('如Int32、String和
在此上下文中支持Guid')
有可行的方法吗?我可能有一个包含10个可能值的状态枚举,并查询其中5个状态。如何以优雅的方式使用Flags enum构造查询
谢谢
更新
这似乎是一个Linq到实体的问题。我认为在LINQtoSQL中它可以工作(不确定,没有测试过)。我不知道EF,但是插入额外的强制转换可以工作吗
var result = from r in db.Records
where ((byte)r.Status & (byte)s) == (byte)r.Status
select r
试着这样做:
[Flags]
public enum Status
{
None = 0,
Active = 1,
Inactive = 2,
Unknown = 4
}
byte status = (byte)(Status.Active | Status.Unknown);
var result = from r in db.Records
select r
where (r.Status & status) != 0
Status s = Status.Active | Status.Unknown;
var result = from r in db.Records
where (s & r.Status) == r.Status
select r
我不确定按位AND运算是否有效,但请尝试将s强制转换为int:
int i = (int)s;
var result = from r in db.Records
select r
where (r.Status & i) == r.Status
您正在使用哪个数据库引擎?引擎可能不支持按位操作
参考资料:以下内容适用于我的C语言#
看看下面的好帖子,它向您展示了以下备选方案:
- 已设置至少一个选定标志
- 设置了完全相同的标志
- 至少包括您选择的那些标志以及更多
hassflag()
数据库中的标志枚举必须为整数。之后,您可以这样尝试:
[Flags]
public enum Status
{
None = 0,
Active = 1,
Inactive = 2,
Unknown = 4
}
byte status = (byte)(Status.Active | Status.Unknown);
var result = from r in db.Records
select r
where (r.Status & status) != 0
Status s = Status.Active | Status.Unknown;
var result = from r in db.Records
where (s & r.Status) == r.Status
select r
r、 状态已经是字节了,我还添加了问题中的强制转换。这不是问题,问题是它不会运行。它编译但不运行。查看问题中的错误。您的查询(如果有效)将只返回状态同时为
活动
和未知
的记录。这就是你想要的吗?不,这是一个或不是一个和。所以'Status s=Status.Active | Status.Unknown;'这是正确的。谢谢@Vasi:这部分是正确的,但是“Status.Active | Status.Unknown
”相当于“1 | 4
”,即5
。因此,你的where
子句实际上是在说“where(r.Status&5)==r.Status
”,这与“where r.Status==5
”,这与(英语中)“wherer.Status
既是活动的
又是未知的
”是一样的!可以将实体转换为可枚举项。请参阅:从EF6.1开始,LINQ to实体支持HASSFLAG。请看:我认为Where中的评估不可翻译为esql或类似的东西。这就是我遇到异常的原因:“无法创建“Closure type”类型的常量值。在此上下文中仅支持基元类型(“如Int32、String和Guid”)。“通过MS SQL Server将LINQ用于实体。否,这是一个无法将枚举结果转换为本机SQL类型的问题。”。因此,使用整数比较可能有效。我认为它无法将位比较转换为eSql。在发布这个问题之前,我在代码中使用了cast-to-byte,但是当我在这里编写这个简短的示例时,我错过了它。所以这不是强制转换问题,我认为这是一个比较问题,不受EF支持。状态列的数据类型是什么?尽管如此,请尝试强制转换到int
。这实际上是为EF LINQ->SQL转换器缺陷找到一个解决方法的全部内容。。。你得试试角落里的箱子。