user869375
user869375

Reputation: 2419

Check value against multiple enum values in IQueryable

I am trying to write an elegant solution to filter a value against multiple Enum values in an IQueryable. Here's what I have got so far:

Extension

public static class EnumExtensions
{
    public static bool IsAny<T>(this T value, params T[] choices)
    where T : Enum
    {
        return choices.Contains(value);
    }
}

Usage

query = query.Where(x => x.Status.IsAny(OrderStatus.Accepted, OrderStatus.Received, OrderStatus.Approved));

But when I execute this, I get following error:

An unhandled exception has occurred while executing the request.
System.InvalidOperationException: The LINQ expression 'DbSet<SalesOrder>
.Where(s => s.DeletedAt == null)
.Where(s => False || s.SellerId == __request_OwnerId_0)
.Where(s => s.Status
    .IsAny(OrderStatus[] { Accepted, Received, Approved, }))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Any pointers on how I can get this working?

Upvotes: 0

Views: 545

Answers (1)

Dai
Dai

Reputation: 155270

You cannot use custom methods inside Linq queries and in Expression<> params for EF. You will need to do it the long-form way:

query = query
    .Where( x =>
        x.Status == OrderStatus.Accepted ||
        x.Status == OrderStatus.Received ||
        x.Status == OrderStatus.Approved
    );

Depending on your RDBMS, you might be able to do it this way though:

static readonly OrderStatus[] _these = new[] { OrderStatus.Accepted, OrderStatus.Received, OrderStatus.Approved };

// ...

query = query.Where( x => _these.Contains( x.Status ) );

...which should be translated to this SQL:

WHERE
    x.Status IN ( 0, 1, 2 )

(Assuming OrderStatus.Accepted == 0, Received == 1, Approved == 2).

Upvotes: 3

Related Questions