johnny 5
johnny 5

Reputation: 20995

Dynamic Where Linq to Entities

I've been doing research on how to dynamically make queries for linq. I'm creating a UI for a web application which allows them to select properties from a DB and set where clauses to build reports dynamically. All of the questions I've seen on stack or other sites reference using Dynamic Linq and LinqKit to Solve the problem, example Here . However I can't find an solution to express the syntax.

// This attempts to grab out a title whose from the Database whose
// Copyright Date equals 2006
propName = "CopyrightDate";
Model.Titles.Where(t => t.GetType().GetProperty(propName).GetValue(t, null) == "2006");

I want to do something like this but in Linq to Entities. Linq to entities doesn't support reflection like that, I do not want to pull out all of the data and run Linq to Object the DB is too Large. Any Suggestions on how to write this in Dynamic Linq. Bonus points if you can cast the type to the property type so It can be evaultuated with standard operators (== , > , < , etc..).

Upvotes: 2

Views: 2714

Answers (2)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112352

What the LINQ-to-entities Where extension method wants, is an Expression<Func<T, bool>>. You can create such an expression like this:

// Create lambda expression: t => t.CopyrightDate == "2006"
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
var lambda = Expression.Lambda<Func<T, bool>>(
     Expression.Equal(
         Expression.Property(parameter, "CopyrightDate"),
         Expression.Constant("2006")
     ),
     parameter
);

where T is the type of your class containing the CopyrightDate property.

var result = context.Titles
    .Where(lambda)
    .ToList();

A somewhat more general solution is:

Expression<Func<T, bool>> Comparison<T>(ExpressionType comparisonType,
                                        string propertyName, object compareTo)
{
    ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
    MemberExpression property = Expression.Property(parameter, propertyName);
    ConstantExpression constant = Expression.Constant(compareTo);
    Expression body = Expression.MakeBinary(comparisonType, property, constant);
    return Expression.Lambda<Func<T, bool>>(body, parameter);
}

Upvotes: 4

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726579

Here is how you can rewrite your query using Dynamic Linq:

var propName = "CopyrightDate";
var propValue = "2006";
Model.Titles.Where(string.Format("{0}=@0", propName), propValue);

string.Format("{0}=@0", propName) produces the query string for the Where clause, which would be "CopyrightDate=@0" in this case. @0 specifies the parameter for the query, which becomes propValue.

Upvotes: 0

Related Questions