2009-09-15 78 views
4

我有一个[国旗]枚举是这样的:如何在Linq中将标志枚举用于实体查询?

[Flags] 
public enum Status 
{ 
    None = 0, 
    Active = 1, 
    Inactive = 2, 
    Unknown = 4 
} 

A状态枚举可以包含两个值,如:

Status s = Status.Active | Status.Unknown; 

现在我需要创建一个LINQ查询(LINQ到ADO.NET实体)并要求记录的状态是以上,即活动或未知;

var result = from r in db.Records 
      select r 
      where (r.Status & (byte)s) == r.Status 

当然,我得到一个错误,因为LINQ to Entities只知道处理Where子句中的基本类型。

错误是:

无法创建 类型“闭合类型”的恒定值。在此上下文中仅支持原始 类型(如Int32,String和 Guid)。

有没有可行的方法?我可能有一个状态枚举有10个可能的值,并查询5个状态。如何以优雅的方式使用Flags枚举构造查询?

谢谢。

更新

这似乎是一个LINQ到实体问题。我认为在LINQ to SQL中起作用(不确定,没有测试过)。

+0

你查询(如果它的工作)只会返回状态是同时'活动'*和*'未知'的记录。那是你要的吗? – LukeH 2009-09-15 11:40:07

+0

不,这是一个或不是一个。所以'Status s = Status.Active | Status.Unknown;”是正确的。谢谢! – 2009-09-15 11:42:30

+0

@Vasi:该部分是正确的,但“Status.Active | Status.Unknown'”相当于“'1 | 4'”,它是'5'。因此,你的'where'子句有效地说“where(r.Status&5)== r.Status'”,这与“r.Status == 5'相同”,这与说(英文)“,其中'r.Status'既是'Active' *又是'Unknown'”! – LukeH 2009-09-15 11:50:06

回答

0

我不知道EF,但可以插入额外的演员工作?

var result = from r in db.Records 
      where ((byte)r.Status & (byte)s) == (byte)r.Status 
      select r 
+0

r。状态已经是字节了,我还在te问题中添加了演员。 这不是问题,问题是它不会运行。它编译但不运行。看到问题中的错误。 – 2009-09-15 11:38:26

0

试试这样说:

byte status = (byte)(Status.Active | Status.Unknown); 

var result = from r in db.Records 
      select r 
      where (r.Status & status) != 0 
+0

我认为Where中的评估不能转换为esql或类似的东西。这就是为什么我得到以下例外的原因: “无法创建类型为'闭包类型'的常量值。在此上下文中仅支持基本类型(如Int32,String和Guid)。 – 2009-09-15 11:40:40

+0

@Vasi:是的,但是您的版本中有错误吗? – LukeH 2009-09-15 12:04:19

+0

我有同样的错误。 – 2009-09-15 12:30:26

1
var result = from r in db.Records 
      where r.Status == s 
      select r 
0

我不能确定,如果按位与运算的工作,但尽力铸造s到一个int:

 int i = (int)s; 
     var result = from r in db.Records 
      select r 
      where (r.Status & i) == r.Status 

哪数据库引擎你使用?可能该引擎不支持按位操作。

参考:http://www.matthidinger.com/archive/2008/02/26/entity-framework-comparison-frustration-explained.aspx

+0

通过MS SQL Server使用LINQ to Entities。 – 2009-09-15 12:25:51

+0

这不是铸造问题。 – 2009-09-15 12:28:23

+0

不,这是一个问题,它不能将枚举的结果转换为原生SQL类型。因此使用整数比较可能会奏效。 – 2009-09-15 12:39:08

0

的folloiwng在C#中对我的作品

public const StatusTypes ActiveAlert = StatusTypes.Accepted | StatusTypes.Delivered; 

     int flags = (int)ActiveAlert; 

     try 
     { 
      var query = from p in model.AlertsHistory 
         where (p.UserId == clientId 
         && (p.Status.HasValue && (p.Status.Value & flags) != 0)) 
         select p; 
      var aList = query.ToList(); 

      return (aList); 


     } 
     catch (Exception exc) 
     { 
      log.Error("Exception getting Alerts History for user.", exc); 
      throw; 
     } 
3

只需使用HasFlag()

var result = from r in db.Records 
     where r.Status.HasFlag(s) 
     select r 
0

在DB标志枚举必须是整数。之后,你可以尝试这样:

Status s = Status.Active | Status.Unknown; 

var result = from r in db.Records 
where (s & r.Status) == r.Status 
select r