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

前端 未结 3 2179
清歌不尽
清歌不尽 2020-12-01 13:45

I am using C# (including Linq) to develop a web application. I have written a generic method to extend Get method of any entity. However when I get the runtime exception \'T

3条回答
  •  既然无缘
    2020-12-01 13:53

    Servy's answer is great and has been very useful for me. I've taken it and expanded/changed it slightly, and will add it onto this to pay back a little bit.

    First off, I renamed the True and False properties to be BaseAnd (instead of True) and BaseOr (instead of false). Mainly this was to be more understandable to me based on how I use them in order to get the results I desire.

    In addition, I added two new generic functions: AddToPredicateTypeBasedOnIfAndOrOr, which takes two ref predicates, one for ands and one for ors and will add an expression onto one of them depending on if it's supposed to be an and or not. This is just to reduce code duplication as my code doesn't know which type it's supposed to be before the app runs.

    CombineOrPreicatesWithAndPredicates takes an initial predicate expression, an and predicate expression and an or predicate expression and combine them in a sql logical way, (and list) and (or list). This is also to reduce code duplication.

    Hope this helps someone out there.

    public static class PredicateBuilder
    {
        public static Expression> BaseAnd() { return f => true; }
        public static Expression> BaseOr() { return f => false; }
    
        public static Expression> Or(
            this Expression> expr1,
            Expression> expr2)
        {
            var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
            return Expression.Lambda>
                  (Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
        }
    
        public static Expression> And(
            this Expression> expr1,
            Expression> expr2)
        {
            var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
            return Expression.Lambda>
                  (Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
        }
    
        public static Expression Replace(this Expression expression,
        Expression searchEx, Expression replaceEx)
        {
            return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
        }
    
        public static Expression> CombineOrPreicatesWithAndPredicates(this Expression> combinedPredicate,
            Expression> andPredicate, Expression> orPredicate)
        {
            combinedPredicate = combinedPredicate ?? BaseAnd();
            if (andPredicate != null && orPredicate!=null)
            {
                andPredicate = andPredicate.And(orPredicate);
                combinedPredicate = combinedPredicate.And(andPredicate);
            }
            else if (orPredicate!=null)
            {
                combinedPredicate = combinedPredicate.And(orPredicate);
            }
            else
            {
                combinedPredicate = combinedPredicate.And(andPredicate);
            }
            return combinedPredicate;
        }
    
        public static void AddToPredicateTypeBasedOnIfAndOrOr(ref Expression> andPredicate,
            ref Expression> orPredicate, Expression> newExpression, bool isAnd)
        {
            if (isAnd)
            {
                andPredicate = andPredicate ?? BaseAnd();
                andPredicate = andPredicate.And(newExpression);
            }
            else
            {
                orPredicate = orPredicate ?? BaseOr();
                orPredicate = orPredicate.Or(newExpression);
            }
        }
    }
    
    internal class ReplaceVisitor : ExpressionVisitor
    {
        private readonly Expression from, to;
    
        public ReplaceVisitor(Expression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }
    
        public override Expression Visit(Expression node)
        {
            return node == from ? to : base.Visit(node);
        }
    }
    

提交回复
热议问题