Enum.HasFlag in LINQ to Entities?

16

我有一个标志,例如:

[Flags]
public enum DaysOfTheWeek
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}
如果我想使用Linq根据包含特定标志的变量进行筛选,我可以尝试在lambda语句中使用Enum.HasFlag来过滤多个标志。
DaysOfWeek weekendFilter = DaysOfTheWeek.Saturday | DaysOfTheWeek.Sunday;
var weekends = allDays.Where(d => d.DayOfWeek.HasFlag(weekendFilter));

目前返回的结果是:

LINQ to Entities不识别方法'Boolean HasFlag(System.Enum)',而这个方法无法转换成存储表达式。


4
EF6.1支持在LINQ-to-Entities中使用HasFlag方法。详见:http://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/3951293-support-enum-hasflag 和 https://entityframework.codeplex.com/workitem/1497。 - Shay
3个回答

29

枚举标志基于二进制操作。

HasFlag = (allDays & (DaysOfTheWeek.Saturday | DaysOfTheWeek.Sunday)) != 0;
你可以将它抽象成一个扩展方法(extension method)如果你愿意的话。
具体回答你的问题:
DaysOfWeek weekendFilter = DaysOfTheWeek.Saturday | DaysOfTheWeek.Sunday;
var weekends = allDays.Where(d => (d.DayOfWeek & weekendFilter) != 0);

我知道你可以在LINQ到SQL中使用这个谓词。它将被翻译成SQL(SQL Server对二进制算术的支持非常好)。不确定EF是否和L2S一样有能力。


我不完全理解您所指的二进制运算。我知道它会将数字转换为字节,并基于数字比较位,但我无法想象我需要如何更新我的lambda表达式。请问如何更新我的weekends lambda使其正常工作? - StuperUser
1
当然。我编辑了我的答案。因为你正在使用EF,所以你不能将操作抽象到一个函数中,因为它无法转换为SQL。 - usr
@Shimmy 我不知道。请测试并在 EF 项目上开启一个 GitHub 问题。他们需要一些东西来跟踪这个功能请求。 - usr

5

0
解决方案是结合了@usr的答案和我所使用的EntityFramework版本的理解。EF4不支持保存枚举,因此实体保存int?并且对象上的枚举属性未映射到EF中。枚举属性将映射到其get/set成员。
例如:
public int? DayOfWeekValue { get; set; }
[NotMapped]
public DaysOfWeek DayOfWeek
{
    get { return (DaysOfWeek)DayOfWeekValue; }
    set { DayOfWeekValue= (int)value; }
}

根据@usr的回答,过滤器需要使用二进制操作来完成。这可以通过将标志设置为扩展字节来实现。
[Flags]
public enum DaysOfTheWeek : byte
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

然后将值和过滤器转换为字节以进行二进制操作:

var weekends = allDays.Where(d => (((byte)d.DayOfWeekValue.Value) & (byte)weekendFilter) != 0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接