“带有语句正文的lambdaexpression式不能转换为expression式树”

在使用EntityFramework时 ,当试图编译以下代码时,出现错误“ A lambda expression with a statement body cannot be converted to an expression tree ”:

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

我不知道错误是什么意思,最重要的是如何解决它。 任何帮助?

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

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

你可以在lambdaexpression式中为IEnumerable集合使用statement body。 试试这个:

 Obj[] myArray = objects.AsEnumerable().Select(o => { var someLocalVar = o.someVar; return new Obj() { Var1 = someLocalVar, Var2 = o.var2 }; }).ToArray(); 

注意:
使用这种方法时请慎重考虑一下,因为这样,所有的查询结果都会在内存中,这可能会对代码的其余部分产生不必要的副作用。

这意味着在lambdaexpression式需要转换为expression式树的地方(例如使用linq2sql的情况下),不能使用带有“语句体”的lambdaexpression式(即使用花括号的lambdaexpression式) 。

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

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

使用这个select的重载:

 Obj[] myArray = objects.Select(new Func<Obj,Obj>( o => { var someLocalVar = o.someVar; return new Obj() { Var1 = someLocalVar, Var2 = o.var2 }; })).ToArray(); 

这意味着一个包含([parameters]) => { some code }; TDelegatetypes的Lambdaexpression式([parameters]) => { some code }; 无法转换为Expression<TDelegate> 。 这是规则。

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

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

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

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

对于你的具体情况,正文是创build一个variables,切换到IEnumerable将强制所有的操作在客户端进行处理,我提出以下解决scheme。

 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#编码约定

LINQ to SQL返回对象正在实现IQueryable接口。 所以对于Select方法谓词参数,你应该只提供一个没有body的lambdaexpression式。

这是因为LINQ for SQL代码不是在程序内部而是在SQL Server等远程端执行的。 这个懒加载执行types是通过实现IQueryable来实现的,其期望的委托被包装在如下的Expression类中。

 Expression<Func<TParam,TResult>> 

expression式树不支持带有body的lambdaexpression式,它仅支持单行lambdaexpression式,如var id = cols.Select( col => col.id );

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

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

以下将按预期工作。

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