2011-03-03 114 views
106

在使用的EntityFramework,我得到的错误“A lambda expression with a statement body cannot be converted to an expression tree”,试图编译下面的代码时:“与语句体lambda表达式不能转换为表达式树”

Obj[] myArray = objects.Select(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() { 
    Var1 = someLocalVar, 
    Var2 = o.var2 }; 
}).ToArray(); 

我不不知道错误的含义,最重要的是如何解决它。任何帮助?

+3

尝试转换到列出这样。 。objects.List()选择(... – 2013-10-10 15:57:24

回答

0

Arr基本类型的Obj? Obj类是否存在?只有Arr是Obj的基本类型,您的代码才能工作。你可以试试这个:

Obj[] myArray = objects.Select(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() 
    { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
}).ToArray(); 
4

不知道更多关于你在做什么(?Linq2Objects,Linq2Entities,LINQ2SQL),这应该使其工作:

Arr[] myArray = objects.AsEnumerable().Select(o => { 
    var someLocalVar = o.someVar; 

    return new Obj() { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
}).ToArray(); 
+8

这迫使可查询到评估 – smartcaveman 2011-03-03 10:32:55

+0

然而,在这种情况下它是好的,因为他叫ToArray的()反正之后 – smartcaveman 2011-03-03 10:38:15

+2

不一定是 - 。谁知道有多大的“o “是什么?它可能有50种属性,当我们想要的是2 – kdawg 2011-04-15 13:46:23

27

这意味着你不能在需要将lambda表达式转换为表达式树(例如使用linq2sql时)的地方使用带有“语句体”的lambda表达式(即使用花括号的lambda表达式)。

+17

你......稍微改写了错误。@Tim罗杰斯的回答是更好 – vbullinger 2013-02-27 18:18:38

+4

+1定义什么是‘语句体’是。 – TomNysetvold 2013-03-21 22:05:33

+1

@vbullinger你是对的程度,但在更普遍的意义(LINQ到SQL的上下文之外)这是一个更直接的答案。它帮助我与AutoMapper错误 – mlhDev 2014-12-30 15:52:40

69

objects Linq-To-SQL数据库上下文吗?在这种情况下,您只能在=>运算符的右侧使用简单的表达式。原因是,这些表达式并没有被执行,而是被转换为SQL来针对数据库执行。 尝试此

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar, 
    Var2 = o.var2 
}).ToArray(); 
1

这意味着其含有([parameters]) => { some code };TDelegate类型的Lambda表达式不能被转换为Expression<TDelegate>。这是规则。

简化查询。您提供的一个可以改写为以下,将编译:

Arr[] myArray = objects.Select(o => new Obj() 
       { 
        Var1 = o.someVar, 
        Var2 = o.var2 
       }).ToArray(); 
59

您可以使用的语句体在兰巴表达式IEnumerable的集合。 试试这个:

Obj[] myArray = objects.AsEnumerable().Select(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() 
    { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
}).ToArray(); 

注意:
使用此方法时,因为这样一来,你将不得不在内存中的所有查询结果仔细想想,可能对你的代码的其余部分不必要的副作用。

+3

+1我喜欢这个!'添加AsEnumerable()'maskes我的问题消失! – Joel 2013-07-09 11:40:32

+5

氏s是真正的解决方案,公认的答案是很难在某些情况下 – 2013-08-02 10:47:34

+8

不,这不是真正的答案申请。这会让你的查询在客户端执行。请参考此问题的详细信息:http://stackoverflow.com/questions/33375998/optimize-linq-to-sql-statement-that-has-foreign-key-access/33376119 – 2015-10-27 19:09:28

2

使用此重载的选择:

Obj[] myArray = objects.Select(new Func<Obj,Obj>(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() 
    { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
})).ToArray(); 
+0

这适用于我,但与Entity Framework一起使用时,此解决方案会阻止dbcontext首先将所有行加载到内存中,就像AsEnumerable()那样? – parliament 2014-11-23 21:57:52

+1

@议会:为了防止加载所有行到内存中,你应该使用'Expression >'。 – Mohsen 2014-11-25 05:42:32

0

针对您的特殊情况下,身体被用于创建一个变量,并切换到IEnumerable将迫使所有的操作要在客户端的处理,笔者建议解决方案

Obj[] myArray = objects 
.Select(o => new 
{ 
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here 
    Info = o, 
}).Select(o => new Obj() 
{ 
    Var1 = o.SomeLocalVar, 
    Var2 = o.Info.var2, 
    Var3 = o.SomeLocalVar.SubValue1, 
    Var4 = o.SomeLocalVar.SubValue2, 
}).ToArray(); 

编辑:重命名为C#编程约定

0

的LINQ to SQL的返回对象正在实施IQueryable接口。因此,对于Select方法谓词参数,您应该只提供没有主体的单个lambda表达式。

这是因为LINQ的SQL代码是不是里面的程序,而不是远程端如SQL Server或其他执行。此延迟加载执行类型是通过实施IQueryable的其中其期望委托被包裹在表达型类象下面实现。

Expression<Func<TParam,TResult>> 

的表达式树不支持lambda表达式与身体和其与只支持单行lambda表达式像var id = cols.Select(col => col.id);

所以如果你试试下面的代码将无法工作。

Expression<Func<int,int>> function = x => { 
    return x * 2; 
} 

以下内容将按预期工作。

Expression<Func<int,int>> function = x => x * 2;