Search code examples
c#linqlambdaexpression-trees

Lambda Expression With Contains Not Working


I'm new to Lambda Expressions and I'm having some problems getting the output that I want. More specifically, I'm having trouble with getting the LINQ contains part of the Lambda Expression correct.

Here's what I have so far:

// The following line is what I want for my Final Result
var distinctValues = db.Equipment.Where(m => m.Model != null && m.Model.Contains(SearchTerm)).Select(m => m.Model).Distinct().ToList();

var queryableData = db.Equipment.AsQueryable();

var parameterExpression = Expression.Parameter(typeof(Equipment), Column);
var constant = Expression.Constant(null);

var property = Expression.Property(parameterExpression, Column);
var expression1 = Expression.NotEqual(property, constant);
var expression2 = Expression.Equal(property,constant);

Expression callContains = Expression.Call(typeof(Queryable), "Contains", new[] { <string> } );

var lambda1 = Expression.Lambda<Func<Equipment, bool>>(expression1, parameterExpression);
var lambda2 = Expression.Lambda<Func<Equipment, string>>(property, parameterExpression);
var lambda3 = Expression.Lambda<Func<Equipment, bool>>(callContains, parameterExpression);
var compiledLambda1 = lambda1.Compile();
var compiledLambda2 = lambda2.Compile();

I'm passing in any property and a search term and I want to generate the equivalent of the LINQ Query above as a Lambda Expression that starts with "var distinctValues". I'm having trouble with the line that starts with "Expression callContains".

Any assistance is much appreciated.

Thanks,

Pete


Solution

  • Thank you Xanatos. With your help I was able to solve my issue. Here's the final solution that I've come up with. Just a few minor changes:

      // m => 
                    var parameterExpression = Expression.Parameter(typeof(Equipment), "m");
    
                    // m.Model
                    var modelProperty = Expression.Property(parameterExpression, Column);
                    // m.Model != null
                    var nonNullExpression = Expression.NotEqual(modelProperty, Expression.Constant(null, typeof(string)));
    
                    // SearchTerm
                    var searchTermConstant = Expression.Constant(SearchTerm);
    
                    // m.Model.Contains(SearchTerm)
                    var containsExpression = Expression.Call(modelProperty, "contains", null, searchTermConstant);
    
                    // m.Model != null && m.Model.Contains(SearchTerm)
                    var andExpression = Expression.AndAlso(nonNullExpression, containsExpression);
    
                    var lambda1 = Expression.Lambda<Func<Equipment, string>>(modelProperty, parameterExpression);
                    var lambda2 = Expression.Lambda<Func<Equipment, bool>>(andExpression, parameterExpression);
    
                    var compiledLambda1 = lambda1.Compile();
                    var compiledLambda2 = lambda2.Compile();
    
                    var distinctValues1 = db.Equipment.Where(compiledLambda2).Select(compiledLambda1).Distinct().ToList();
    

    First, I used a different overload for containsExpression. Second, I wanted the model property as a parameter. Basically, I wanted to pass in a variable property (Column) and variable searchterm. That's it.