How to use flags enums in Linq to Entities queries?

可紊 提交于 2019-12-30 03:30:07

问题


I have a [Flags] enum like this:

[Flags]
public enum Status
{
  None = 0,
  Active = 1,
  Inactive = 2,
  Unknown = 4
}

A Status enum may contain two values such as:

Status s = Status.Active | Status.Unknown;

Now I need to create a linq query (LINQ to ADO.NET Entities) and ask for records whose status is s above, that is Active or Unknown;

var result = from r in db.Records
             select r
             where (r.Status & (byte)s) == r.Status

Of course I get an error, because LINQ to Entities only knows to handle primitive types in the Where clause.

The error is:

Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

Is there a workable way? I may have a status Enum with 10 possible values and to query for 5 of the statuses. How do I construct the query using Flags enum in an elegant way?

Thanks.

Update

This seems to be a Linq to Entities problem. I think in LINQ to SQL it works (not sure, didn't tested).


回答1:


Just use HasFlag()

var result = from r in db.Records
         where r.Status.HasFlag(s)
         select r



回答2:


Take a look at the following good post, it shows you the following alternatives:

  • At least one of the selected flags set
  • Exactly the same flags set
  • At least those flags you selected and more

https://timdams.wordpress.com/2011/02/14/using-enum-flags-to-write-filters-in-linq/#comment-30




回答3:


var result = from r in db.Records
             where r.Status == s
             select r



回答4:


I don't know EF, but could inserting additional casts work?

var result = from r in db.Records
             where ((byte)r.Status & (byte)s) == (byte)r.Status
             select r



回答5:


Try it like this:

byte status = (byte)(Status.Active | Status.Unknown);

var result = from r in db.Records
             select r
             where (r.Status & status) != 0



回答6:


I am unsure if a bitwise AND-operation will work, but try casting s to an int:

        int i = (int)s;
        var result = from r in db.Records
             select r
             where (r.Status & i) == r.Status

Which database engine are you using? Possibly the engine does not support bitwise operations.

Reference: http://www.matthidinger.com/archive/2008/02/26/entity-framework-comparison-frustration-explained.aspx




回答7:


The folloiwng works for me in C#

    public const StatusTypes ActiveAlert = StatusTypes.Accepted | StatusTypes.Delivered;

        int flags = (int)ActiveAlert;

        try
        {
            var query = from p in model.AlertsHistory
                        where (p.UserId == clientId
                        && (p.Status.HasValue && (p.Status.Value & flags) != 0))
                        select p;
            var aList = query.ToList();

            return (aList);


        }
        catch (Exception exc)
        {
            log.Error("Exception getting Alerts History for user.", exc);
            throw;
        }



回答8:


In DB Flags enum must be integer. After that you can try it like this:

Status s = Status.Active | Status.Unknown;

var result = from r in db.Records
where (s & r.Status) == r.Status
select r


来源:https://stackoverflow.com/questions/1426577/how-to-use-flags-enums-in-linq-to-entities-queries

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!