加入 Linq 时如何使用表达式获取动态谓词
How to get dynamic predicate using expressions when joining in Linq
我编写了一个静态方法,它将使用表达式 api 为不同类型的字段提供适当的谓词 lambda。
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();
}
如果我像这样在 linq 中执行单个查询操作,上面的代码可以正常工作:
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; }
}
现在,如果我在 MyClass 实体上进行联接
var data = DbContext.MyClass
.Join(DbContext.Detail, mc => mc.Id, detail => detail.Id, (m, d) =>
new { m = m, d = d})
.Where(del);
上面几行给出了编译时错误
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>'
我知道 .Where()
现在需要一个具有 m 和 d 的匿名类型,但不确定如何解决这个问题.
我对 Expression API 还很陌生。不知道怎么实现。
我试图通过创建匿名类型变量来实现这一点,但那是一个变量而不是类型本身,无法将其传递给 Process<T>()
。
您的 Process
方法的结果是 MyClass
类型对象的 Where
子句,因此您不能使用它来过滤匿名对象 { m, d }
。而是在 Join
:
之前过滤
var data = DbContext.MyClass.Where(del);
.Join(DbContext.Detail,
mc => mc.Id,
detail => detail.Id,
(m, d) => new { m, d }
);
我编写了一个静态方法,它将使用表达式 api 为不同类型的字段提供适当的谓词 lambda。
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();
}
如果我像这样在 linq 中执行单个查询操作,上面的代码可以正常工作:
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; }
}
现在,如果我在 MyClass 实体上进行联接
var data = DbContext.MyClass
.Join(DbContext.Detail, mc => mc.Id, detail => detail.Id, (m, d) =>
new { m = m, d = d})
.Where(del);
上面几行给出了编译时错误
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>'
我知道 .Where()
现在需要一个具有 m 和 d 的匿名类型,但不确定如何解决这个问题.
我对 Expression API 还很陌生。不知道怎么实现。
我试图通过创建匿名类型变量来实现这一点,但那是一个变量而不是类型本身,无法将其传递给 Process<T>()
。
您的 Process
方法的结果是 MyClass
类型对象的 Where
子句,因此您不能使用它来过滤匿名对象 { m, d }
。而是在 Join
:
var data = DbContext.MyClass.Where(del);
.Join(DbContext.Detail,
mc => mc.Id,
detail => detail.Id,
(m, d) => new { m, d }
);