2017-12-05 20 views
0

EnitityFramework 6を​​使用して、入力タイプ(データベースエンティティ)のIQueryableを取得し、出力タイプのIQueryableを返すメソッドを作成します。コンバータクラスには、入力タイプの単一インスタンスを出力タイプの単一インスタンスに変換するメソッドもあります。 .Selectラムダパラメータに変換する方法を使用すると、実行時例外が発生します。Linq to Entities InvertType in IQueryable

System.NotSupportedException:メソッド「バー変換(フー)」メソッド、およびこの方法を認識しないエンティティへのLINQは、ストアに翻訳することはできません表現。

internal static class FooConverter 
{ 
    internal static IQueryable<Bar> Convert(IQueryable<Foo> foos) 
    { 
     return foos.Select(d => Convert(d)); 
    } 

    internal static Bar Convert(Foo foo) 
    { 
     return new Bar 
     { 
      Id = foo.Id, 
      Number = foo.Number, 
      Valid = foo.Valid ?? false, 
     }; 
    } 
} 

研究は、LINQのエンティティに私のConvert(Foo)方法からSQLを生成することができないので、私はいくつかのリファクタリングをしたことを示唆しています。両方の方法で初期化を複製すると、すべてが機能します。

internal static class FooConverter 
{ 
    internal static IQueryable<Bar> Convert(IQueryable<Foo> foos) 
    { 
     return foos 
      .Select(d => new Bar 
      { 
       Id = foo.Id, 
       Number = foo.Number, 
       Valid = foo.Valid ?? false, 
      )}; 
    } 

    internal static Bar Convert(Foo foo) 
    { 
     return new Bar 
     { 
      Id = foo.Id, 
      Number = foo.Number, 
      Valid = foo.Valid ?? false, 
     }; 
    } 
} 

しかし、今ではコードが重複しています。冗長性を排除するためにConvert(Foo)Convert(IQueryable<Foo>)から呼び出すことは可能ですか?

+2

問題は、式中のIQueryable取引ということです。クエリプロバイダは、式ツリーを歩き回って、それを知っているすべてのものをSQLに変換します。しかし、それは表面上のものだけを翻訳することができます。任意のメソッド呼び出しを、投影に必要なNewExpression/MemberInitExpressionsに変換する方法を理解していません。変換する必要がない場合は、式を返してから、デリゲートにコンパイル()して、LINQ以外の方法で使用するようにしてください。 – pinkfloydx33

+0

ありがとうございますpinkfloyd。私は表現式に精通していませんでしたが、あなたのコメントは私を正しい方向に導いてくれました。 https://msdn.microsoft.com/en-us/library/bb335710(v=vs.110).aspx – chadnt

答えて

0

pinkfloydx33のクレジット彼のコメントは私にExpression<TDelegate>をもたらしました。それが他の人にとって価値がある場合に備えて、私の全面的な解決策を投稿します。

internal static class FooConverter 
{ 
    internal static Expression<Func<Bar, Foo>> FooToBarExpression = 
     (d) => new Bar 
     { 
      Id = foo.Id, 
      Number = foo.Number, 
      Valid = foo.Valid ?? false, 
     }; 

    internal static IQueryable<Bar> Convert(IQueryable<Foo> foos) 
    { 
     return foos.Select(FooToBarExpression)}; 
    } 

    internal static Bar Convert(Foo foo) 
    { 
     return FooToBarExpression.Compile().Invoke(foo); 
    } 
} 

参考:https://msdn.microsoft.com/en-us/library/bb335710(v=vs.110).aspx

+0

私はこれにAutoMapperを使用します。 –

+0

これを行うなら、 'Func 'という私的な静的変数を保存し、 'Compile'を一度呼び出してその変数に格納します。次に、Convertメソッドを代理人を呼び出すパススルーとして機能させます。それ以外の場合は、メソッドを呼び出すたびに式をコンパイルするオーバーヘッドがあります。 – pinkfloydx33