关于这个主题已经存在一些问题(例如实体框架中的Expression.Invoke?),但是,我无法找到适合我具体情况的答案.我想定义一个这样的方法:
public IQueryable<Customer> GetCustomers(Expression<Func<Customer, bool>> condition)
{
return from p in ctx.Customers.AsExpandable()
where condition.Compile()(p)
select p;
}
Run Code Online (Sandbox Code Playgroud)
AsExpandable方法来自LinqKit(正如前面提到的线程中所建议的那样).但是,当我尝试像他的方式调用我的方法时:
var customers = GetCustomers(c => c.ID == 1);
Run Code Online (Sandbox Code Playgroud)
它抛出InvalidCastException:
无法将类型为"System.Linq.Expressions.InstanceMethodCallExpressionN"的对象强制转换为"System.Linq.Expressions.LambdaExpression".我究竟做错了什么?
在我为谓词构建器看到的所有示例中,PredicateBuilder.True
如果要构建"和"表达式条件以及PredicateBuilder.False
构建"或"表达式条件,它将显示一个起始表达式.
我的问题是,这种情况总是如此,如果是这样的话,为什么不能简单地推断出这一点.我怀疑必定会有一些情况,你正在构建一个"和"表达式,并希望从错误开始.与"或"相反
任何人都可以向我解释这个吗?
这就是我想要做的事情:
class MyDbContext : DbContext
{
private static Expression<Func<MyClass, int>> myExpression1 = x => /* something complicated ... */;
private static Expression<Func<Item, int>> myExpression2 = x => /* something else complicated ... */;
public object GetAllData()
{
return (
from o in MyClassDbSet.AsExpandable()
select new
{
data1 = myExpression1.Invoke(o), // problem 1
data2 = o.Items.Select(myExpression2.Compile()) // problem 2
}
);
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
myExpression
必须与我的查询保持分离,因为我想在多个LINQ查询中重用它.
更新2:
分离myExpression
成myExpression1
和myExpression2
明确指出,我想单独重用他们的事实.
更新3:
添加了LINQkit示例.
问题1抛出:无法将"System.Linq.Expressions.FieldExpression"类型的对象强制转换为"System.Linq.Expressions.LambdaExpression".
问题2抛出:内部.NET Framework数据提供程序错误1025.
我一直在使用LinqKit来创建通用查询.
一直困扰我的一件事是你总是要测试过滤器中发送的值是否有效.
例如:假设我有一个字符串过滤器.条件可以是Equal,StartsWith,EndsWith和Contains.
我的方法看起来像这样:
public List<MyModel> Get(MyModelFilter filter)
{
if (string.IsNullOrEmpty(filter.prop))
{
predicate = predicate.And(_myModel => myModel.Prop.Contains(filter.prop));
}
// Plus a giant amount of if's with multiple filters
return DbSet.AsExpandable()
.Where(predicate)
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
为了结束这一堆If,我决定创建一个通用方法来将过滤器应用于属性.我的想法是传递将应用过滤器的属性和过滤器定义,并封装表达式创建逻辑
它将是这种类型的东西:
public List<MyModel> Get(MyModelFilter filter)
{
predicate = predicate.And(_myModel => myModel.Prop, filter.PropFilterDefinition);
// Goodnye If's, Only others filter impl
return DbSet.AsExpandable()
.Where(predicate)
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
为此,我创建了一些扩展方法来处理这个问题
public static Expression<Func<TPredicate, bool>> And<TPredicate>(
this ExpressionStarter<TPredicate> predicate,
Func<TPredicate, string> property, StringFilterDefinition filter,
bool ignoreNull = true)
{
if …
Run Code Online (Sandbox Code Playgroud)