C# 实体框架代码优先延迟加载

C# 实体框架代码优先延迟加载,c#,entity-framework,entity-framework-4,ef-code-first,lazy-loading,C#,Entity Framework,Entity Framework 4,Ef Code First,Lazy Loading,我有两个对象类 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; } // Navig

我有两个对象类

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; }
}
公共类用户
{
公共Guid Id{get;set;}
公共字符串名称{get;set;}
//航行
公共ICollection产品{get;set;}
}
公共类产品
{
公共Guid Id{get;set;}
//航行
公共用户{get;set;}
公共Guid用户_Id{get;set;}
公共字符串名称{get;set;}
}
当我使用dataContext加载用户时,我得到的产品列表为null(这是确定的)

如果我在产品列表中添加“虚拟”关键字

public virtual ICollection<Product> Products { get; set; }
公共虚拟ICollection产品{get;set;}
当我加载用户时,我也会得到产品列表

为什么会这样?我认为“virtual”关键字用于不加载实体,除非您明确说明这一点(使用“Include”语句)


我想我完全弄错了

我想你需要的是一个属性,它是进入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?
这是错误的

“virtual”关键字用于不加载实体,除非 显式(使用“Include”语句)

延迟加载意味着当您第一次访问集合或导航属性时,实体将自动加载,并且这种加载将透明地进行,就像它们总是使用父对象加载一样

当您指定要查询的属性时,使用“包含”是按需加载

virtual
关键字的存在仅与延迟加载相关
virtual
关键字允许实体框架运行时为实体类及其属性创建动态代理,从而支持延迟加载。如果没有虚拟,将不支持延迟加载,并且集合属性将为null


事实上,您可以在任何情况下使用“include”,但如果不延迟加载,这是访问集合和导航属性的唯一方法。

您可以使用context.ContextOptions.LazyLoadingEnabled=false;要强制上下文不使用LazyLoadingWith dbContext,它将是context.Configuration.LazyLoadingEnabled=false;不使用“virtual”:User=db.Users.First();在调试模式下,user.Products为空。使用“virtual”关键字:User=db.Users.First();在调试模式下,user.Products是Products@RaraituL:正如archil已经提到的,您必须在代码优先方法中使用virtual关键字,以使延迟加载成为可能。然后您可以打开或关闭它。但是在“user.Products”之前,上下文是“closed”的,所以如果存在上下文,延迟加载将如何工作?“延迟加载意味着当您第一次访问集合时将自动加载实体”这意味着如果我永远不会访问user.Products属性,则不会加载产品,是吗?@RaraituL是的,没错。调试时,您实际上可以访问属性,如果支持延迟加载,则会加载属性。所以您可以使用sql事件探查器或类似的工具来调试发送到数据库的实际查询。@archil:如果我不使用collection编写virtual并使用include,那么它也会在只需要时加载某些内容,对吗?比如延迟加载?那么有什么区别呢?