“带有语句正文的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 };
TDelegate
types的Lambdaexpression式([parameters]) => { some code };
无法转换为Expression<TDelegate>
。 这是规则。
简化您的查询。 你提供的一个可以被重写为以下,并将编译:
Arr[] myArray = objects.Select(o => new Obj() { Var1 = o.someVar, Var2 = o.var2 } ).ToArray();
Arr
是Obj
的基本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;