Entity Framework 4.1 POCO Code Firstでは、仮想キーワードはどのような効果をもたらしますか?


229

virtualEFコードファーストでのプロパティに使用された場合のキーワードは効果があります?。誰かがさまざまな状況でのすべての影響を説明できますか?

たとえば、遅延読み込みを制御できることはわかっています。ICollection/ one-to-many関係プロパティでvirtualキーワードを使用すると、デフォルトで遅延読み込みされますが、virtualキーワードを省略した場合は、熱心にロードされます。

virtualPOCOエンティティを使用したEFで、キーワードは他にどのような影響を与える可能性がありますか?virtualすべてのプロパティで使用するようにデフォルトにするか、デフォルトで使用しないようにする必要がありますか?

回答:


194

これまでのところ、私はこれらの影響を知っています。

  • 遅延読み込みvirtual特に指定しない限り、ICollectionはすべて遅延読み込みされます。
  • より効率的な変更の追跡。以下のすべての要件を満たしている場合は、仮想プロパティをフックすることにより、変更追跡でより効率的な方法を使用できます。リンクから:

    変更追跡プロキシを取得するための基本的なルールは、クラスはパブリック、非抽象、または非密封でなければならないということです。クラスは、永続化されるすべてのプロパティのパブリック仮想ゲッター/セッターも実装する必要があります。最後に、コレクションベースのリレーションシップナビゲーションプロパティICollection<T>のみを宣言する必要があります。これらは、具体的な実装や、派生する別のインターフェースにすることはできませんICollection<T>(遅延読み込みプロキシとの違い)

これを説明するもう1つの便利なリンクは、MSDNのPOCOプロキシを作成するため要件です


52
プロパティを仮想化する理由は他にありません。ナビゲーションプロパティは遅延読み込みの場合は仮想としてマークされ、スカラープロパティは変更の追跡の場合は仮想としてマークされます。
Ladislav Mrnka、2011

10
ナビゲーションプロパティとは何ですか?スカラープロパティとは何ですか?
アビッドアリ

9
@AbidAli:ナビゲーションプロパティは外部キー(エンティティクラスタイプ)または1対多の関係(タイプICollection <>)であると思います。スカラープロパティは、基本型(int、string、..)またはComplexType(基本型の単なる構造体)です。
スコットスタッフォード

2
" public virtual byte[] bigData { get; set; }"遅延読み込みですか?
AechoLiu 2013年

9
bytes []は熱心に読み込まれ、遅延できるのは外部キーだけです。その列をフェッチしたくない場合は、レコード全体をフェッチしないでください.Select(a=>new { fields you want })
スコットスタッフォード

63

この仮想キーワードは、エンティティフレームワークからのデータの読み込み(遅延読み込み、積極読み込み、および明示読み込み)のトピックに関連しています。

遅延読み込みでデータを読み込む場合は、virtualキーワードを使用する必要があります。

遅延読み込みは、エンティティまたはエンティティのコレクションが最初にアクセスされたときにデータベースから自動的に読み込まれるプロセスです。

たとえば、以下で定義されているブログエンティティクラスを使用する場合、関連する投稿は、投稿ナビゲーションプロパティに初めてアクセスしたときに読み込まれます。

public class Blog 
{  
     public int BlogId { get; set; }  
     public string Name { get; set; }  
     public string Url { get; set; }  
     public string Tags { get; set; }  
     public virtual ICollection<Post> Posts { get; set; }  
}

Postsコレクションの遅延読み込みは、Postsプロパティを非仮想にすることでオフにできます。

遅延読み込みがオフの場合でも、積極的な読み込み(Includeメソッドを使用)または関連エンティティを明示的に読み込み(Loadメソッドを使用)すると、Postsコレクションの読み込みを実行できます。

熱心な読み込み:

using (var context = new BloggingContext()) 
{ 
    // Load all blogs and related posts 
    var blogs1 = context.Blogs 
                          .Include(b => b.Posts) 
                          .ToList(); 
}

明示的に読み込んでいます:

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 

    // Load the posts related to a given blog 
    context.Entry(blog).Collection(p => p.Posts).Load(); 
}

1
仮想(遅延読み込み)を使用するときにN + 1の問題を回避するにはどうすればよいですか?たとえば、context.Blogs.ToList();などです。その後、テーブルを結合せず、ブログの数だけ選択クエリを実行します。
エキスパート

1
@Expertwannabeレイジーロードを使用していても、への呼び出しで明示的にイーガーロードを要求できますInclude()
モンシニョール2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.