2009-09-17 7 views
11

私は基本的に2つのエンティティフレームワークオブジェクトのラッパーであるプレーンな古いCLRオブジェクトを持っています。このようにして、このラッパーオブジェクトをMVCフレームワークの強く型付けされたビュー。マイfooのラッパークラスは非常に単純です:LINQ to Entitiesの厳密に型指定されたオブジェクトを初期化する

public class FooWrapper 
{ 
    public FooWrapper(Foo f, Bar b) 
    { 
     this.FooObject = f; 
     this.BarObject = b; 
    } 

    public Foo FooObject { get; private set; } 
    public Bar BarObject { get; private set; } 
} 

次のように私は私のListFoosWithBars機能のために、これまで持っていることは次のとおりです。

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet 
             join b in tempBar on f.ID equals b.foos.ID 
             select new FooWrapper(f, b)); 
    return results; 
} 

これは動作しません明らかにLINQのエンティティには、パラメータ化をサポートしていないため、次のような例外がスローされます。「LINQ to Entitiesでは、パラメータのないコンストラクタと初期化子のみがサポートされています。」私は同じ結果を達成する別の方法があるのだろうかと思いましたか?

答えて

20

あなたFooWrapperにパラメータなしのコンストラクタを追加して、代わりにオブジェクトの初期化を使用し、そのような場合:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 

    IEnumerable<FooWrapper> results = (
     from f in _entities.FooSet 
     join b in tempBar on f.ID equals b.foos.ID 
     select new FooWrapper() 
     { 
      FooObject = f, 
      BarObject = b 
     }); 

    return results; 
} 
+3

同じことが入力されていれば勝ちます。 – AdamSane

+0

パーフェクト、ありがとう! –

3

異なる初期化してみてください。

public class FooWrapper 
{ 
    public FooWrapper() { } 

    public Foo FooObject { get; set; } 
    public Bar BarObject { get; set; } 
} 


public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 

    IEnumerable<FooWrapper> results = (
     from f in _entities.FooSet 
     join b in tempBar on f.ID equals b.foos.ID 
     select new FooWrapper 
     { 
      FooObject = f, 
      BarObject = b 
     }); 

    return results; 
} 
+1

イニシャライザでタイプ名の後に()を省略すると+1します。 :) –

12

[OK]を、しかし、どのような場合は、FooObjectをしたいですBarObjectは読み込み専用ですか?それは、オブジェクトに対してコンストラクタを使用する能力を否定することは、私には少し後退しているようです。

このシナリオでは、オブジェクトの初期化を利用するために、良いカプセル化の慣行を破っている人が多くいます。

6

を見つけましたか?このようにして、パラメータのないコンストラクタを作成する必要はなく、それは必要なものです。

コードはほぼ良好でした。これに変更してください:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID) 
{ 
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID); 
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet.AsEnumerable() 
             join b in tempBar on f.ID equals b.foos.ID 
             select new FooWrapper(f, b)); 
    return results; 
} 

今日は同じ問題がありました。 1つのパラメータコンストラクタを持つクラスがありました。このコンストラクタは、プロパティで返されたprivate readonlyフィールドを、getでのみセットし、セットではないもので埋めました。

+0

これはこれまでのところ、この問題の最も良い解決策です! –

+8

私はAsEnumerableを呼び出すことによって基本的にEntityフレームワークの利点を無効にしていますが、このアプローチには非常に注意が必要です。 FooSetテーブルからすべてのレコードを効果的に取り込み、メモリ内でローカルに結合を実行するように指定したら、何千(または何百万)ものレコードがある場合のパフォーマンスの影響について考えてみてください。 – Alan

+0

@サントスこのアプローチでは、16台のテーブルのLINQ文でマシンが停止し、結果を返すのに約5分かかります。それに匹敵するSQLステートメントでほとんど瞬間がありました。 – wonea

関連する問題