Error "The LINQ expression node type 'Invoke' is not supported in LINQ to Entities" in where clause inside the method

c# entity-framework linq linq-to-entities

Question

When I run my search:

rs.Select(x => x.id).ToArray();

This is the error I get:

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities

This technique is what causes the mistake, which is possibly func(x):

public IQueryable<TEntity> Compare<TEntity>(IQueryable<TEntity> source, Func<TEntity, int> func)
{
     IQueryable<TEntity> res = source;

     if (!this.LBoundIsNull) res = res.Where(x => func(x) >= _lBound);
     if (!this.UBoundIsNull) res = res.Where(x => func(x) <= _uBound);

     return res;
}

I use the approach in the following manner:

Document doc = new Document();
doc.Number = new RangeValues(lBound, null);

using (MyEntities db = new MyEntities())
{
    var rs = db.documents;
    if (doc.Number != null) rs = doc.Numero.Compare(rs, x => x.number);

    long[] id = rs.Select(x => x.id).ToArray();
}

What is the issue?

1
2
9/21/2017 11:47:59 AM

Accepted Answer

You must take the following actions in order to achieve your goals:

public static IQueryable<TEntity> Compare<TEntity>(IQueryable<TEntity> source, Expression<Func<TEntity, int>> func)
{
    IQueryable<TEntity> res = source;

    if (!LBoundIsNull) 
    {
        Expression ge = Expression.GreaterThanOrEqual(func.Body, Expression.Constant(_lBound));
        var lambda = Expression.Lambda<Func<TEntity, bool>>(ge, func.Parameters);
        res = res.Where(lambda);
    }

    if (!UBoundIsNull)
    {
        Expression le = Expression.LessThanOrEqual(func.Body, Expression.Constant(_uBound));
        var lambda = Expression.Lambda<Func<TEntity, bool>>(le, func.Parameters);
        res = res.Where(lambda);
    }

    return res;
}

As you can see, expression-tree plumbing will be necessary. The method is invoked in the same manner as before.

Now, is using LinqKit as proposed by @jbl actually feasible? Yes, by just shaking the magic wand.

using LinqKit;

public static IQueryable<TEntity> Compare<TEntity>(IQueryable<TEntity> source, Expression<Func<TEntity, int>> func)
{
    IQueryable<TEntity> res = source;

    if (!LBoundIsNull)
    {
        Expression<Func<TEntity, bool>> lambda = x => func.Invoke(x) >= _lBound;
        res = res.Where(lambda.Expand());
    }

    if (!UBoundIsNull)
    {
        Expression<Func<TEntity, bool>> lambda = x => func.Invoke(x) <= _uBound;
        res = res.Where(lambda.Expand());
    }

    return res;
}

Take note of how theInvoke() and Expand() LinqKit techniques.

6
4/9/2015 2:32:47 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow