web-dev-qa-db-ja.com

ナビゲーションプロパティは仮想である必要があります-ef coreでは不要ですか?

私がEFで覚えているように ナビゲーションプロパティは仮想でなければなりません

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; }  
}

しかし、私は EF Core を見て、それを仮想のものとして見ていません:

public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }

もう必要ありませんか?

40
Alexan

virtualは、EFでは決してrequiredでした。遅延読み込みのサポートが必要な場合にのみ必要でした。

EFコアでは遅延読み込みはまだサポートされていません なので、現在virtualには特別な意味はありません。遅延読み込みサポートを追加する場合(および追加する場合)(そうするための plan があります)。

更新:EF Core 2.1以降では、 遅延読み込み がサポートされるようになりました。ただし、 Microsoft.EntityFrameworkCore.Proxies パッケージを追加せず、UseLazyLoadingProxiesを介して有効にするとすぐに、元の答えが適用されます。

ただし、そうすると、初期実装にオプトインコントロールが存在しないため、状況は完全に変わります-itrequiresallナビゲーションプロパティはvirtualになります。それは私には意味がありません、あなたはそれが修正されるまでそれを使用しない方が良いでしょう。本当に遅延読み込みが必要な場合は、代替の プロキシなしの遅延読み込み アプローチを使用します。この場合も、virtualは重要ではありません。

62
Ivan Stoev

受け入れられた答えが書かれて以来、物事は変わりました。 2018年、 Entity Framework Core 2.1の時点で遅延読み込みがサポートされるようになりました 2つの異なるアプローチに対して。

2つの簡単な方法はプロキシを使用することであり、これにはvirtualで定義するために遅延ロードが必要なプロパティが必要です。リンクされたページから引用するには:

遅延読み込みを使用する最も簡単な方法は、Microsoft.EntityFrameworkCore.Proxiesパッケージをインストールし、UseLazyLoadingProxiesへの呼び出しで有効にすることです。 [...] EF Coreは、オーバーライド可能なナビゲーションプロパティの遅延読み込みを有効にします。つまり、仮想プロパティであり、継承可能なクラス上にある必要があります。

そして、提供されたサンプルコードは次のとおりです。

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public virtual Blog Blog { get; set; }
}

プロキシなしで遅延読み込みを行う別の方法があります。これは、データ型のコンストラクタにILazyLoaderを注入することです。 これはここで説明されています

要するに、遅延読み込みを実行するには、プロキシありとプロキシなしの2つの方法があります。 virtualrequiredであり、プロキシで遅延読み込みをサポートする場合にのみ必要です。そうでなければ、そうではありません。

18
Matt

仮想キーワードは必要ありません...オプションです。

何が変わりますか?

1。プロパティvirtualを宣言する場合:

メインオブジェクトのクエリ時に、仮想プロパティ(デフォルト)はすぐにはロードされません。データベースにアクセスするか、そのコンポーネントの1つにアクセスしようとした場合にのみ、データベースから取得します。

そして、これは遅延読み込みと呼ばれます。

2。非仮想と宣言した場合:

プロパティは(デフォルトで)メインエンティティの他のすべてのプロパティとともにすぐにロードされます。これは、プロパティにアクセスする準備ができたことを意味します。すでに取得されています。このプロパティにアクセスするため、エンティティはデータベースを再度クエリする必要はありません。

これは、積極的な読み込みと呼ばれます。

私の意見:

より頻繁に私は熱心にロードする(非仮想)を選択しますが、ほとんどの場合、すべてのエンティティのすべてのプロパティをクエリバックせずに使用する必要があります(本当にすべてをすばやくしたい場合は高速です)が、このプロパティにアクセスする場合たまに(何もリストしない)だけで、この情報以外の残りの情報だけが必要な場合が多いので、それを仮想化して、このプロパティが少数のアクセスで残りのクエリを遅くしないようにします。

これが明確だったことを願って...

例:

私が仮想を使用しない場合(熱心に):

foreach(var line in query)
{
    var v = line.NotVirtual; // I access the property for every line
}

仮想または遅延読み込みを使用する場所:

foreach(var line in query)
{
   if(line.ID == 509)        // because of this condition
   var v = line.Virtual; // I access the property only once in a while
}

最後に一つだけ :

データベースの1 000行を超えるクエリを実行しない場合、選択したものは何も大きな影響を与えません。また、これらのプロパティを仮想として宣言することができます。逆の方法でテストしたい場合は、これを行う必要があります(Entity 4.0):

context.LazyLoadingEnabled = false;

仮想効果をキャンセルします。

編集

EFの新しいバージョンの場合:

WhateverEntities db = new WhateverEntities() 
db.Configuration.LazyLoadingEnabled = false;
16

EF Coreでは、デフォルトで遅延ロードを推奨しないパスを選択しています。また、私はこの機能がこの問題に続いてまだ実装されていないと思います。

https://github.com/aspnet/EntityFramework/issues/3312

EFの以前のバージョンでは、仮想ナビゲーションプロパティは関連するエンティティの遅延読み込みを許可していました。

今のところ、ナビゲーションプロパティの読み込みは.Include(...)でのみ達成できると思います

編集:

Coreでサポートされている関連エンティティを読み込む方法はいくつかあります。興味がある場合: https://docs.Microsoft.com/en-us/ef/core/querying/related-data

3

更新:EF Core 2.1で計画されている遅延読み込みの初期実装では、ナビゲーションプロパティを仮想として宣言する必要があります。 https://github.com/aspnet/EntityFrameworkCore/issues/10787 を参照してください。遅延読み込みの進行状況を追跡する一般的な方法については、 https://github.com/aspnet/EntityFrameworkCoreを参照してください。/issues/10509

1
SvenAelterman