web-dev-qa-db-ja.com

Entity Framework Code First Lazy Loading

私は2つのオブジェクトクラスを持っています

public class User
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    // Navigation
    public ICollection<Product> Products { get; set; }
}

public class Product
{
    public Guid Id { get; set; }

    // Navigation
    public User User { get; set; }
    public Guid User_Id { get; set; }

    public string Name { get; set; }
}

DataContextを使用してユーザーを読み込むと、製品のリストがnullになります(これで問題ありません)。

製品リストに「仮想」キーワードを追加すると、

public virtual ICollection<Product> Products { get; set; }

ユーザーを読み込むと、製品リストも取得します。

なんでこんなことが起こっているの? 「仮想」キーワードは、これを明示しない限り(「含める」ステートメントを使用して)エンティティをロードしないために使用されると思いました

私はそれをすべて間違っていたと思う

30
Catalin

これは間違っています

「virtual」キーワードは、明示的に指定しない限り、エンティティをロードしないために使用されます(「Include」ステートメントを使用)

遅延読み込みとは、コレクションまたはナビゲーションプロパティに最初にアクセスしたときにエンティティが自動的に読み込まれることを意味します。これは、常に親オブジェクトと共に読み込まれたかのように透過的に行われます。

クエリするプロパティを指定するときに、 "include"を使用するとオンデマンドでロードされます。

virtualキーワードの存在は、遅延読み込みのみに関連しています。 virtualキーワードを使用すると、エンティティフレームワークランタイムがエンティティクラスとそのプロパティの動的プロキシを作成し、それによって遅延読み込みがサポートされます。仮想なしでは、遅延読み込みはサポートされず、コレクションプロパティでnullを取得します。

実際には、どのような場合でも「include」を使用できますが、遅延ロードなしでコレクションとナビゲーションプロパティにアクセスする唯一の方法です。

66
archil

into efコンテキストでありながら、遅延ロードの対象となるプロパティを要求していると思います。

using (var db = new Context())
{
    var user = db.Users.Where(...);

    var products = user.Products; // being loaded right away
}

そのままにしてみてください:

User user;
using (var db = new Context())
{
    user = db.Users.Where(...);

    // I guess you will need here:
    // .Include(u => u.Products)
}
var products = user.Products; // what error will you get here?
4
abatishchev