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データベースコンテキストですか?その場合、=>演算子の右側にある単純な式のみを使用できます。その理由は、これらの式は実行されず、データベースに対して実行されるSQLに変換されるためです。これを試して
Arr[] myArray = objects.Select(o => new Obj() {
Var1 = o.someVar,
Var2 = o.var2
}).ToArray();
IEnumerableコレクションのlamba式でステートメント本体を使用できます。これを試してください:
Obj[] myArray = objects.AsEnumerable().Select(o =>
{
var someLocalVar = o.someVar;
return new Obj()
{
Var1 = someLocalVar,
Var2 = o.var2
};
}).ToArray();
注意:
この方法を使用する場合は慎重に検討してください。この方法では、すべてのクエリ結果がメモリに格納され、残りのコードに望ましくない副作用が生じる可能性があるためです。
これは、ラムダ式を式ツリーに変換する必要がある場所(たとえば、linq2sqlを使用する場合)で、「ステートメント本体」を持つラムダ式(中括弧を使用するラムダ式)を使用できないことを意味します。 。
あなたが何をしているのか(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();
LINQ to SQL戻りオブジェクトは、IQueryable
インターフェイスを実装していました。したがって、Select
メソッドの述語パラメーターには、本体のない単一のラムダ式のみを指定する必要があります。
これは、LINQ for SQLコードは、SQLサーバーなどのリモート側ではなく、プログラム内で実行されるためです。この遅延読み込み実行タイプは、IQueryableを実装することで達成されました。IQueryableの期待デリゲートは、以下のようなExpressionタイプクラスでラップされています。
Expression<Func<TParam,TResult>>
式ツリーは、本体を持つラムダ式をサポートせず、var id = cols.Select( col => col.id );
のような単一行のラムダ式のみをサポートします
そのため、次のコードを試しても機能しません。
Expression<Func<int,int>> function = x => {
return x * 2;
}
以下は期待どおりに機能します。
Expression<Func<int,int>> function = x => x * 2;
これは、([parameters]) => { some code };
を含むTDelegate
型のLambda式はExpression<TDelegate>
に変換できないことを意味します。それがルールです。
クエリを簡素化します。指定したものは、次のように書き換えてコンパイルできます。
Arr[] myArray = objects.Select(o => new Obj()
{
Var1 = o.someVar,
Var2 = o.var2
} ).ToArray();
Arr
はObj
の基本型ですか? Objクラスは存在しますか? ArrがObjの基本型である場合にのみ、コードは機能します。代わりにこれを試すことができます:
Obj[] myArray = objects.Select(o =>
{
var someLocalVar = o.someVar;
return new Obj()
{
Var1 = someLocalVar,
Var2 = o.var2
};
}).ToArray();
特定の場合、本体は変数を作成するためのものであり、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#コーディング規約の名前を変更