首页 > 解决方案 > 在 .Net 5.0.4 Entity Framework 查询中使用具有多个值的 [Flags]

问题描述

我有一个带有 [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查询,则不会返回任何结果,因为翻译后的 SQL 如下所示:

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

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

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

我可能错过了一些东西,但我只是没有看到它。

标签: entity-framework-core.net-5enum-flags

解决方案


.Net5 EF不.HasFlag应该支持

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

由于某种原因,按位运算限制为一个值

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

true如果标志中设置的位域或位域也在当前实例中设置;否则,false

然后在备注中:

HasFlag方法返回以下布尔表达式的结果。

thisInstance And flag = flag

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

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

不久,HasFlagAll. 没有专用的方法Any,因此您应该使用它的直接按位运算等效项,即

(value & flags) != 0

在您的样本中

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

推荐阅读