1

2エンティティ:MemberComment
MemberICollection<Comment> Comments私はmember.Comments.Take(x) EFを使用するたびに.Takeを考慮していない関連にアクセスして、最初のコードを使用して(x)の

は、データベースからすべてのコメントを取得するクエリを生成しています。 それはそうなのでしょうか?
プロパティはICollectionなので、ですか? EFにTake(x)の要素を考慮する方法がありますか?context.Comments.Where(c=>c.MemberId==member.Id).Take(x)を使用してコードをリファクタリングする必要がありますか?

+0

Ladislav Mrnkaのアプローチは、実際にあなたが求めていることを再考する必要があります。おそらく、Take()を使用するときにこれを適用するメソッドを用意することができます。 –

答えて

1

EFによって生成されたプロキシクラスは、ナビゲーションプロパティのレイジーロードのみを提供しますが、クエリを評価しません。 member.Commentsプロパティにアクセスすると、コメントエンティティがデータベースからロードされ、クエリがメモリに適用されます。これを避けるには、オブジェクトセット上で直接実行されるクエリでコメントを取得する必要があります(既に与えられている例のように)。

EFがこのプロパティへのアクセスを傍受するためにナビゲーションプロパティからIQueryableを返さなければならないので、これは設計によるものだと考えていますが、これはうまくカバーされていないと思います。

あなたはすでにこれを処理する方法について説明しましたが、これはかなりのものではありません。別のオプションは、メンバーオブジェクトの元のクエリを作成するときに、何らかの理由でEFにプロパティを部分的にロードするよう指示することです。私はそれを見ていきますが、私はすでにそのアプローチに間違っているかもしれない1つか2つの考えを考えることができます。

編集 いくつかの研究と試行錯誤の後、私はDbSet<Member>ではなくDbSet<Comment>上で直接実行してMemberオブジェクトを返すことができ、別のアプローチ、思い付くことができませんでした。

var query = from m in catalog.Members 
      select new 
      { 
       Id = m.Id, 
       Name = m.Name, 
       Comments = m.Comments.Take(1) 
      }; 

その後、メモリ内のメンバーオブジェクトに変換することができ、もちろん、それはとにかくのコンテキスト(=無変更の追跡)に接続されない:私は匿名オブジェクトを使用して可能です。上記のサンプルクエリでは、匿名型の代わりにMemberのインスタンスを作成することはできません.EFは非複合型のみを作成できるためです(「Member」がエンティティであることをコンテキストが認識しているので推測しています)。

3

@ J。 TihonはEFの仕組みです。遅延読み込みプロパティにアクセスすると、EFは常にコレクション全体をロードし、ロードされたコレクションでLinq式が評価されます。これを回避するには、説明どおりにクエリを使用する必要がありますが、クエリの結果はナビゲーションプロパティに読み込まれません。これを解決するには、代わりに遅延ロードの明示的なロードを使用することができます。これは、2件のコメントをあなたのCommentsプロパティを埋める必要があります

context.Entry(member) 
     .Collection(m => m.Comments) 
     .Query() 
     .OrderBy(...) // Take requires some sorting 
     .Take(2) 
     .Load(); 

+0

私はちょうどこれを試してみましたが、実際にIntelliTraceは正しいクエリが実行されたことを教えてくれます。 –

関連する問題