I have an Enum with [Flags] attribute like this:
[Flags]
public enum FlagStatus
{
Value1 = 1
, Value2 = 2
, Value3 = 4
}
And my query for EF like this:
x => x.Status.HasFlag(flagStatus)
Now if I set the flagStatus = FlagStatus.Value1
the query works fine since I set value to 1).
@__request_Status_0 = 1
WHERE ([o].[StatusId] & @__request_Status_0) = @__request_Status_0)
But if I set it to flagStatus = FlagStatus.Value1 | FlagStatus.Value3
the query returns no results as the translated SQL looks like this:
@__request_Status_0 = 5
WHERE ([o].[StatusId] & @__request_Status_0) = @__request_Status_0)
And since that's is not a valid Id int the Status field no results are returned.
So the question now is this: Isn't .HasFlag supposed to be supported by .Net5 EF or is bitwise operation for some reason limited to one value? And if so why have bitwise operations support at all?
I probably missed something, but I just don't see it.
Isn't
.HasFlag
supposed to be supported by .Net5 EF
Supported means translated to SQL instead of throwing runtime exception, so apparently it is.
is bitwise operation for some reason limited to one value
No, it's not. But when used with multiple values, it has different meaning than what you seem to be expecting. The documentation of the Enum.HasFlags CLR method says that it returns
true
if the bit field or bit fields that are set in flag are also set in the current instance; otherwise,false
.
and then in remarks:
The
HasFlag
method returns the result of the following Boolean expression.
thisInstance And flag = flag
which is exactly what EF Core is doing.
Translating it to simple words, it checks if ALL bits in flags are present in value (the equivalent All
operation for sets). While you seem to be expecting it to has Any
semantics.
Shortly, HasFlag
is for All
. There is no dedicated method for Any
, so you should use its direct bitwise operation equivalent which is
(value & flags) != 0
In your sample
x => (x.Status & flagStatus) != 0