简体   繁体   中英

Enum.HasFlag in LINQ to Entities?

I have a flag eg

[Flags]
public enum DaysOfTheWeek
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

If I want to use Linq to filter based on a variable containing particular flags, I can try to use Enum.HasFlag in a lambda statement to filter for more than one flag eg

DaysOfWeek weekendFilter = DaysOfTheWeek.Saturday | DaysOfTheWeek.Sunday;
var weekends = allDays.Where(d => d.DayOfWeek.HasFlag(weekendFilter));

This currently gives:

LINQ to Entities does not recognize the method 'Boolean HasFlag(System.Enum)' method, and this method cannot be translated into a store expression.

Enum flags are based on binary operations.

HasFlag = (allDays & (DaysOfTheWeek.Saturday | DaysOfTheWeek.Sunday)) != 0;

You can abstract that into an extension method if you wish.

To answer your question concretely:

DaysOfWeek weekendFilter = DaysOfTheWeek.Saturday | DaysOfTheWeek.Sunday;
var weekends = allDays.Where(d => (d.DayOfWeek & weekendFilter) != 0);

I know that you can use this predicate with LINQ to SQL. It will be translated to SQL (SQL Server supports binary arithmetic just fine). Not sure if EF is equally capable as its LINQ supports is generally far inferior to L2S.

Looks like it has been fixed in EF 6.1.

Regarding EF Core however, check this .

The solution is a combination of @usr's answer, and an understanding of the version of EntityFramework I am using. EF4 doesn't support saving Enums, so the entities save an int? and the property for the enum on the object isn't mapped into EF. The property for the enum will maps to member for its get/set.

eg

public int? DayOfWeekValue { get; set; }
[NotMapped]
public DaysOfWeek DayOfWeek
{
    get { return (DaysOfWeek)DayOfWeekValue; }
    set { DayOfWeekValue= (int)value; }
}

As, per @usr's answer, the filter will need to be done with binary operations. This can be done, by setting the flag to extend byte

[Flags]
public enum DaysOfTheWeek : byte
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

then casting the value and the filter as bytes to do the binary operation:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM