Wurd
Wurd

Reputation: 475

Using dynamic linq in EF Linq to Entities

I'm building up a Linq.Expressions.Expression at runtime and then I thought I would use it like so:

Type myTypeVariable = viewModel.typeVariable;
DbContext db = //get entity model for myTypeVariable
Expression myExpression = //build a predicate of myTypeVariable from viewModel
var query = (IQueryable<myType>)db.Set(myTypeVariable);
var results = query.Provider.CreateQuery(myExpression); 

The error I'm getting is at the .CreateQuery() stage: "Linq to Entities query expresions can only be constructed from instances that implement the IQueryable interface." My confusion comes from the fact that if the last line it replaced with this I get results?: results = query.Where(c=>c.ID>0).ToList();

I've mostly been following this: https://msdn.microsoft.com/en-us/library/bb882637.aspx

How do I get results from my DbSet using my Expression predicate?

Upvotes: 0

Views: 1293

Answers (1)

phil soady
phil soady

Reputation: 11348

Usually building expression trees is the hard part. See Building expression trees for more details.

The are tools and libraries out there to help. The use fascades or tools to help build expressions. eg Predicate Builder

You can pass the expression to a generic repository to do dynamic Linq in EF. For example:

public virtual IQueryable<TPoco> GetList(Expression<Func<TPoco, bool>> predicate) {
        return  Context.Set<TPoco>().Where(predicate);
    }

 // a small sample building an expression for Contains string 
 public static Expression<Func<TPoco, bool>> GetContainsPredicate<TPoco>(string propertyName, string containsValue)
    {
        // (tpoco t) => t.propertyName.Contains(value ) as expression 
        var parameterExp = Expression.Parameter(typeof(TPoco), @"t");
        var propertyExp = Expression.Property(parameterExp, propertyName);
        MethodInfo method = typeof(string).GetMethod(@"Contains", new[] { typeof(string) });
        var someValue = Expression.Constant(containsValue, typeof(string));
        var containsMethodExp = Expression.Call(propertyExp, method, someValue);

        return Expression.Lambda<Func<TPoco, bool>>(containsMethodExp, parameterExp);
    }

USAGE:

 var  someExp = MyTool.GetContainsPredicate("FIELDNAME","SomeString");
 var resultQueryable = myRepOfTpoco.GetList(someExp )  ;

Upvotes: 1

Related Questions