I wrote a static method which will give appropriate predicate lambda using expression api for different type of fields.
static Func<T, bool> Process<T>(string type)
{
ParameterExpression parameter = Expression.Parameter(typeof(T));
Expression predicate = Expression.Constant(true);
if (type == "Start")
{
Expression prop = Expression.Property(parameter, type);
Expression filter = Expression.LessThan(prop, Expression.Constant(DateTime.Now));
predicate = Expression.AndAlso(predicate, filter);
}
//TODO: more if statments to come
var lambda = Expression.Lambda<Func<T, bool>>(predicate, parameter);
return lambda.Compile();
}
The above code works fine if I do a single query operation in linq like this:
var del = Process<MyClass>("Start");
var data = DbContext.MyClass.Where(del); //gets the result data
public class MyClass
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public long Id { get; set; }
}
Now, if I do a join on the MyClass entity
var data = DbContext.MyClass
.Join(DbContext.Detail, mc => mc.Id, detail => detail.Id, (m, d) =>
new { m = m, d = d})
.Where(del);
The above lines are giving compile time error
Error CS1929 'IQueryable<<anonymous type: MyClass m, Detail d>>' does not contain a definition for 'Where' and the best extension method overload 'EnumerableRowCollectionExtensions.Where<MyClass>(EnumerableRowCollection<MyClass>, Func<MyClass, bool>)' requires a receiver of type 'EnumerableRowCollection<MyClass>'
I understand that .Where()
now expects an anonymous type which has m and d but not sure how to resolve this.
I'm pretty new to Expression API. Not sure how to achieve.
I've tried to achieve that by creating anonymous type variable, but that is a variable and not the type itself to pass it to Process<T>()
.
The result of your Process
method is a Where
clause for objects of type MyClass
, so you can't use it to filter anonymous objects { m, d }
. Instead filter before the Join
:
var data = DbContext.MyClass.Where(del);
.Join(DbContext.Detail,
mc => mc.Id,
detail => detail.Id,
(m, d) => new { m, d }
);