2013-05-03 20 views
5

私はEFモデルを最初にPOCOエンティティとカスタムDbContextで使用しています。私の問題は、LazyLoadingEnabled=falseの設定は何にも影響しないことです。ナビゲーションプロパティはまだ読み込まれています。 以下は私の例を簡略化したものです。LazyLoadingEnabled設定がEF 5で機能しないようです

エンティティプログラム。

namespace Domain.Entities 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Program 
    { 
     public Program() 
     { 
      this.Programs = new HashSet<Program>(); 
     } 

     public int Id { get; set; } 
     public string Title { get; set; } 
     public string Description { get; set; } 
     public System.DateTime StartDate { get; set; } 
     public System.DateTime EndDate { get; set; } 
     public Nullable<int> ProgramId { get; set; } 

     public virtual ICollection<Program> Programs { get; set; } 
     public virtual Program OwnerProgram { get; set; } 
    } 
} 

DbContext:プログラムが他のプログラムの一部にすることができます。ここ

namespace Infrastructure.Model 
{ 
    public class ProgramContext : DbContext 
    { 
     public ProgramContext() 
      : base("name=MyContainer") 
     { 
      Configuration.LazyLoadingEnabled = false; 
     } 

     public DbSet<Program> Programs { get; set; } 
    } 
} 

が、私はそれを使用する方法です:

上記のサンプルでは
private ProgramContext _dbContext = new ProgramContext(); 

// GET api/program 
public IEnumerable<Program> GetPrograms() 
{ 
    List<Program> list = _dbContext.Programs.ToList(); 
    return list; 
} 

、EFはまだプログラムをロードしますProgramクラスのOwnerProgramプロパティを使用します。仮想キーワードを削除しようとしましたが、プロキシの作成を無効にして、モデル自体にLazyLoadingEnabled=falseを確認しました。

何か不足していますか?

答えて

6

あなたが見ている効果は、リレーションシップフィックスアップと呼ばれています。

実際には、ナビゲーションプロパティはではなく、が明示的にロードされています。クエリ_dbContext.Programs.ToList()は、Programsテーブル全体のみをデータベースからロードします。これは、WHERE句のない単純なSQLクエリ(SELECT * FROM ProgramsTableなど)であり、関連する行にはJOINが含まれていません。

program.Programsprogram.OwnerProgramのナビゲーションプロパティにアクセスすると、ここで遅延読み込みが発生しません(これを無効にしても、ダイナミックプロキシを無効にしても実際にはできません)。

ナビゲーションプロパティは、クエリ(結果としてすべてのプログラムをロードする)がナビゲーションプロパティが参照できるすべてのプログラムをロードしたために、マテリアライズされます。 EFは、それらの関連するエンティティが既にメモリ内にあることを検出し、それらを自動的にナビゲーションプロパティに配置します。あなたはすべてプログラムをロードしていないだけで、例えば、単一のものがあれば

あなたはこれを確認することができます

Program program = _dbContext.Programs.FirstOrDefault(); 

さて、program.Programsprogram.OwnerProgramnullになります - ロードprogramが一部でない限り、独自のprogram.OwnerProgramコレクションのものまたはOwnerProgramです。

+1

ありがとう、これは私が見ているものです。 .Include()を使用していない限り、EFでナビゲーションプロパティを読み込まないようにする方法はありますか? – gixen

+0

@gixen:言われたように、実際には「読み込み中」ではありません。リレーションシップフィックスアップは、すでに読み込まれているナビゲーションコレクションと参照にエンティティを配置します。したがって、クエリのオーバーヘッドはありません。読み込み後にエンティティを変更する場合は、変更の追跡が必要で、この動作を無効にすることはできません。読み取り専用の状況で変更を追跡することなく、 '_dbContext.Programs.AsNoTracking()。ToList()'を試すことができます。しかし、この場合に役立つかどうかはわかりません。 – Slauma

+0

私がこの答えを得ているのは、オープン・コンテキストで遅延ロード・ナビゲーション・プロパティーを使わずにオブジェクト・グラフ全体をEFにロードする方法がないことです。 OR .Include( "NavigationProtperyName")はナビゲーションプロパティを読み込むために明示的に呼び出すことができますが、各クエリで必要です。 –

2

「EFは、まだプログラム クラスのプログラムとOwnerProgramプロパティをロードする」これは正しい動作ですが、代わりにレイジーナビゲーションプロパティをロードするのではなく、熱心にそれらをロードします。

これは、ナビゲーションプロパティ値の取得に必要なデータベースクエリが、Programエンティティが取得され、ナビゲーションプロパティが入力されたときに直ちに実行されることを意味します。

LazyLoadingEnabledtrueに設定すると、ナビゲーションプロパティにアクセスしようとするまで、これらのクエリはトリガーされません。これは、ナビゲーションプロパティの上にマウスを置いてデバッガをアタッチしているときにも当てはまります。実際にはエンティティが遅延ロードされていないと思うかもしれません。デバッガがナビゲーションプロパティにアクセスしています。 Entity Frameworkによって読み込まれます。

this oneなどのSQLプロファイラを実行すると、コードをデバッグするときにクエリがトリガされたタイミングを正確に表示できます。

0

上記のサンプルでは、​​EFはProgramクラスのProgramおよびOwnerProgram プロパティをまだ読み込みます。仮想 キーワードを削除してプロキシの作成を無効にしてみましたが、モデル自体に LazyLoadingEnabled = falseがあることを確認しました。

何か不足していますか?

これらのプロパティを初期化するデフォルトのコンストラクタを削除する必要があります。

関連する問題