在 .Net 5.0.4 Entity Framework 查询中使用具有多个值的 [Flags]

Using [Flags] with multiple values in .Net 5.0.4 Entity Framework query

我有一个带有 [Flags] 属性的枚举,如下所示:

[Flags]

public enum FlagStatus
    
{
    
    Value1 = 1
    
  , Value2 = 2
    
  , Value3 = 4
    
}

我对 EF 的查询是这样的:

x => x.Status.HasFlag(flagStatus)

现在,如果我设置 flagStatus = FlagStatus.Value1,查询工作正常,因为我将值设置为 1)。

@__request_Status_0 = 1
WHERE ([o].[StatusId] & @__request_Status_0) = @__request_Status_0)

但是如果我将它设置为 flagStatus = FlagStatus.Value1 | FlagStatus.Value3 查询 returns 没有结果,因为翻译的 SQL 看起来像这样:

@__request_Status_0 = 5
WHERE ([o].[StatusId] & @__request_Status_0) = @__request_Status_0)

并且由于这不是状态字段中的有效 ID,因此不会返回任何结果。

所以现在的问题是:.Net5 EF 不应该支持 .HasFlag 还是出于某种原因将按位运算限制为一个值?如果是这样,为什么完全支持按位运算?

我可能错过了什么,但我就是没看到。

Isn't .HasFlag supposed to be supported by .Net5 EF

支持的意思是翻译成 SQL 而不是抛出运行时异常,显然是这样。

is bitwise operation for some reason limited to one value

不,不是。但是当与多个值一起使用时,它的含义与您似乎期望的不同。 Enum.HasFlags CLR 方法的文档说它 returns

true if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, false.

然后在备注中:

The HasFlag method returns the result of the following Boolean expression.

thisInstance And flag = flag

这正是 EF Core 正在做的事情。

将其翻译成简单的词,它会检查标志中的所有位是否都存在于值中(等效于集合的 All 操作)。虽然您似乎期望它具有 Any 语义。

很快,HasFlag 用于 AllAny 没有专门的方法,所以你应该使用它的直接按位运算等价物,即

(value & flags) != 0

在你的样本中

x => (x.Status & flagStatus) != 0