使用LINQkit在LINQ to Entities Select中调用Expression

这就是我想要做的:

class MyDbContext : DbContext { private static Expression<Func> myExpression1 = x => /* something complicated ... */; private static Expression<Func> 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分隔为myExpression1myExpression2 ,以明确我希望单独重用它们的事实。

更新3:

添加了LINQkit示例。

问题1抛出:无法将“System.Linq.Expressions.FieldExpression”类型的对象强制转换为“System.Linq.Expressions.LambdaExpression”。

问题2抛出:内部.NET Framework数据提供程序错误1025。

关于使用LinqKit时的第一个问题,您需要在.Invoke()之前将表达式分配给局部变量。 在这个问题上可以找到更完整的解释。

第二个问题是select方法接受一个类型的对象:

 Expression> 

这意味着您必须提供一个lambda表达式,接受一个TSource对象作为参数并返回一个TResult对象。

您的TSource对象是Item,即您进行查询的表。 你的TResult在你的例子中是一个int,就是你在表达式上定义的。

因此,您必须在第二个表达式上调用.Invoke(),将Item对象作为参数传递,方法与传递MyClassDbSet对象“o”的方式相同。 实际上,两个select语句只有语法上的差异,它们本质上也是一样的。

你不应该在表达式上调用.Compile(),这会产生一个:

 Func 

哪个是表达式树的编译版本的委托,不能转换为SQL表达式。 更多信息可以在这里找到。

它应该与以下更改一起使用:

 class MyDbContext : DbContext { private static Expression> myExpression1 = x => /* something complicated ... */; private static Expression> myExpression2 = x => /* something else complicated ... */; public object GetAllData() { Expression> myLocalExpression1 = myExpression1; Expression> myLocalExpression2 = myExpression2; return ( from o in MyClassDbSet.AsExpandable() select new { data1 = myLocalExpression1.Invoke(o), data2 = o.Items.Select(item => myLocalExpression1.Invoke(item)) } ); } } 

您可以尝试仅使用委托而不是表达式:

  private static Func myExpression = x => /* something complicated ... */; 

这种方法的问题在于,将从数据库中检索整个MyClass,而不是仅计算表达式所需的字段。