4

这就是我想要做的:

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:

分开myExpressionmyExpression1明确myExpression2我想单独重用它们的事实。

更新 3:

将 LINQkit 添加到示例中。

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

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

4

2 回答 2

7

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

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

Expression<Func<TSource, TResult>>

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

您的 TSource 对象是 Item,即您从中进行查询的表。您的 TResult 在您的示例中是一个 int ,这就是您在表达式中定义的内容。

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

而且您不应该在表达式上调用 .Compile() ,这会产生:

Func<TSource, TResult>

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

它应该适用于以下更改:

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)) 
            }
        );
    }
}
于 2014-01-22T01:06:11.430 回答
0

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

  private static Func<MyClass, int> myExpression = x => /* something complicated ... */;

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

于 2013-07-16T20:39:18.230 回答