这就是我想要做的事情:
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
}
);
}
}
更新:
myExpression
必须与我的查询保持分离,因为我想在多个LINQ查询中重用它。
更新2:
将myExpression
分隔为myExpression1
和myExpression2
,以明确我希望单独重复使用它们。
更新3:
添加LINQkit示例。
问题1 抛出:无法将“System.Linq.Expressions.FieldExpression”类型的对象强制转换为“System.Linq.Expressions.LambdaExpression”。
问题2 抛出:内部.NET Framework数据提供程序错误1025。
答案 0 :(得分:6)
关于使用LinqKit时的第一个问题,您需要在.Invoke()之前将表达式分配给局部变量。可以在this question找到更完整的解释。
第二个问题是select方法接受类型为
的对象Expression<Func<TSource, TResult>>
这意味着您必须提供一个lambda表达式,接受一个TSource对象作为参数并返回一个TResult对象。
您的TSource对象是Item,即您进行查询的表。你的TResult在你的例子中是一个int,就是你在表达式上定义的。
因此,必须在第二个表达式上调用.Invoke(),将Item对象作为参数传递,方法与传递MyClassDbSet对象“o”的方式相同。实际上,两个选择语句只有语法上的差异,它们必然会做同样的事情。
你不应该在表达式上调用.Compile(),这会产生一个:
Func<TSource, TResult>
哪个是表达式树的编译版本的委托,不能转换为SQL表达式。可以找到更多信息here。
它应该可以使用以下更改:
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()
{
Expression<Func<MyClass, int>> myLocalExpression1 = myExpression1;
Expression<Func<MyClass, int>> myLocalExpression2 = myExpression2;
return (
from o in MyClassDbSet.AsExpandable()
select new
{
data1 = myLocalExpression1.Invoke(o),
data2 = o.Items.Select(item => myLocalExpression1.Invoke(item))
}
);
}
}
答案 1 :(得分:0)
您可以尝试仅使用委托而不是表达式:
private static Func<MyClass, int> myExpression = x => /* something complicated ... */;
这种方法的问题在于,将从数据库中检索整个MyClass,而不是仅计算表达式所需的字段。