在Entity Framework查询中使用带有标志的枚举

tob*_*ias 7 .net c# linq entity-framework entity-framework-4

我有一个类似下面的枚举类型

  [Flags]
    public enum WeekDays
    {

        Monday = 1,
        Tuesday = 2,
        Wednesday = 4,
        Thursday = 8,
        Friday = 16,
        Saturday = 32,
        Sunday = 64,
    }


   WeekDays dw = WeekDays.Friday | WeekDays.Monday | WeekDays.Saturday;

   int dwInt = (int)dw;

   var list = query.Where(f => f.FromDateTime.DayOfWeek == dwInt "??????????? what can i do there????").ToList();
Run Code Online (Sandbox Code Playgroud)

Dav*_*d W 11

我将猜测你不确定要在查询中添加什么来过滤你在源代码中列出的日子.

鉴于你的源代码片段,我认为可以安全地推断dwInt被用作位掩码,而DayOfWeek将有一个位置"设置"以指示一周中的给定日期.在此基础上,你想要做的是在哪里用dwInt在DayOfWeek字段上执行逻辑按位AND,然后检查结果是否大于0,意味着设置了所需的星期几"bits"之一你的目标领域.我相信这可以解决问题:

var list = query.Where(f => (f.FromDateTime.DayOfWeek & dwInt) >0).ToList()
Run Code Online (Sandbox Code Playgroud)

如果我错误地解释了您的问题,请原谅.

  • 请注意,这不适用于实体框架查询,因为它不会转换为 SQL。您必须调用 `ToList()` 并对生成的内存中集合执行 `Where()`。 (2认同)
  • (我知道我正在死灵地这样做,但对于像我这样的随机谷歌用户来说:)“使用 EF 5 为我工作” - 但你的查询在服务器上完成了一半,在本地完成了一半(EF 不理解的部分像位操作,是本地完成),这可能会严重损害性能。EF Core 不支持这种行为,它会抛出异常,让您知道您必须使用 .ToArray() 并在本地执行此操作 - 所以您可以决定“没关系”或“天哪,这很糟糕,让我们尝试一下”提出不同的解决方案”。 (2认同)

you*_*uen 11

从Entity Framework 6.1开始,您可以HasFlag在请求中使用扩展方法.

例如:

query.Where(f => f.FromDateTime.DayOfWeek.HasFlag(WeekDays.Friday | WeekDays.Monday)).ToList();
Run Code Online (Sandbox Code Playgroud)

有关功能请求和实现的详细信息,请参阅https://entityframework.codeplex.com/workitem/1497.


Paw*_*wel 6

[HasFlags]属性在某种意义上非常有趣,除了.ToString()和(AFAIK)Enum.Parse()操作外,它不会影响任何东西.因此,对于非字符串操作,枚举类型是否具有[HasFlags]属性并不重要.枚举在EF中工作的方式是它们只是强制转换为基础类型,并被视为它们是以下整数类型之一int64,int32,int16,byte,sbyte(注意EDM不支持无符号整数类型,因此具有未签名基础类型的枚举将不起作用,并且在数据库中,枚举列只是与上述类型之一对应的类型的列.这意味着基本上任何对整数值(EF支持的类型)有效的操作在枚举值上都是有效的,除非编译器不允许它(我不认为我知道这样的任何操作).这也意味着无论你想把它放在哪里?如果它编译应该工作(Sql Server支持按位操作)


tob*_*ias 3

解决方案在这里

 public static Dictionary<int, int> map = new Dictionary<int, int>() { { 0, 64 }, { 1, 1 }, { 2, 2 }, { 3, 4 }, { 4, 8 }, { 5, 16 }, { 6, 32 } };

//actually,this comes from the user interface, but we should focus on the database layer
WeekDays[] dw = new WeekDays[] {WeekDays.Saturday,WeekDays.Tuesday,WeekDays.Wednesday };
    
int[] systemDayOfWeekList = new int[daysOfWeek.Length];
    
for (int i = 0; i < daysOfWeek.Length; i++)
{
  systemDayOfWeekList[i] = map.FirstOrDefault(e => e.Value == (int)daysOfWeek[i]).Key;
}
    
query = query.Where(f => dayOfWeekList.Contains(((int)SqlFunctions.DatePart("dw", f.FromDateTime))));
Run Code Online (Sandbox Code Playgroud)