0

I have written a query that works fine when I use ToList() at the end of query before calling the predicate, but it throws an exception when I don't use ToList().

I don't want to use ToList() until the complete query is executed on the DB server otherwise, it will fetch thousands of records to memory, so I need to call the predicate once the complete query is executed.

Here is My Query without ToList() :

var myquery = (from p in se.CompanyRepresentatives
                             join qr in questionnaires on p.ID equals qr.RespondentID

                             join ra in se.Responses on qr.ID equals ra.QuestionnaireResponseID into raGroup
                             from res in raGroup.Where(r=> r.QuestionID == 1 || r.QuestionID == 2 || r.QuestionID == 3).DefaultIfEmpty(null)
                             
                             where
                            qr.QuestionnaireID == SurveyEntities.PROJECT_QUESTIONNAIRE_ID
                             select new ResultViewModel
                             {
                                 CompRep = p,
                                 QuestionnaireRes = qr,
                                 Res = raGroup.FirstOrDefault(x =>   x.QuestionID == 1),
                                 ProjectDeliverable = raGroup.FirstOrDefault(x =>   x.QuestionID == 2).Answer,
                                 ProjectDescription = raGroup.FirstOrDefault(x =>  x.QuestionID == 3).Answer,

                             });

    query= myquery.Where(ContainsAny(projectNamelist));

Here at the following line it throws the exception mentioned in title:

var nquery = query.ToList();

Here is my predicate builder :

static Expression<Func<ResultViewModel, bool>> ContainsAny(List<string> filters)
        {
            
            var predicate = PredicateBuilder.True<ResultViewModel>();
            foreach (var filter in filters)
            {
                string newfilter = filter.ToLower();
                predicate = predicate.And(cprep=> cprep.CompRep.CompanyName != null && cprep.CompRep.CompanyName.ToLower().Contains(newfilter)
                                            || ( cprep.CompRep.Email != null && cprep.CompRep.Email.ToLower().Contains(newfilter.ToLower()))
                                            || (  cprep.CompRep.FirstName != null && cprep.CompRep.FirstName.ToLower().Contains(newfilter.ToLower()))
                                            || (cprep.Res.Answer != null && cprep.Res.Answer.ToLower().Contains(newfilter.ToLower()))
                                            || (cprep.CompRep.CompanyDescription != null && cprep.CompRep.CompanyDescription.ToLower().Contains(newfilter.ToLower())));
            }
            return predicate;
        }

Here is PredicateBuilder:

public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }
Engr Umair
  • 130
  • 10
  • What is `PredicateBuilder` here? Also, `And( cprep.CompRep.CompanyName...` doesn't look correct. Shouldn't it be `And(cprep => cprep.CompRep.CompanyName...`? And which EF version is this? – Gert Arnold Dec 16 '22 at 18:40
  • @GertArnold thanks for the correction, I will edit the question to add PredicateBuilder – Engr Umair Dec 16 '22 at 19:00
  • @GertArnold I have updated the question please check – Engr Umair Dec 16 '22 at 19:02
  • 1
    Apparently this is EF6. It doesn't tolerate expression trees with `Invoke` as EF core does. Try Linqkit or [this little gem](https://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/) that has a different solution for the parameter binding problem. – Gert Arnold Dec 16 '22 at 19:16

0 Answers0