实体框架不会懒惰地加载引用和集合属性

时间:2017-04-19 21:32:17

标签: c# entity-framework entity-framework-6 lazy-loading

我有背包和书籍实体。书籍参考背包(一对多)。 我正在创建一个背包和一堆书籍的实例。所以在这种情况下,背包有很多书。我将这些实体保存到数据库中。我正在验证那些已保存到数据库中。当我尝试加载背包时,它加载正常,除导航属性外,所有属性都已设置。我也在检查是否禁用了LazyLoading。我的导航属性具有virtual关键字。 我不确定我做错了什么。如果我尝试使用Include()加载背包,则会加载书籍:

dbContext.Backpacks.Where(b=>b.Name!="").Include("Books").FirstOrDefault()

我想弄清楚为什么懒得加书?加载这本书时遇到同样的问题。当我装书时,它没有附加背包。我看到BackpackId就在那里。

在我的属性getter / setter中,我有一些会被解雇的逻辑,但我不确定这可能是一个什么问题。

4 个答案:

答案 0 :(得分:3)

由于手头的信息有限,我可以看到您的问题的以下解释。

禁用延迟加载或代理创建

确保启用延迟加载和代理创建,第一个没有后者不起作用。

dbContext.Configuration.ProxyCreationEnabled = true;
dbContext.Configuration.LazyLoadingEnabled = true;

(详见Locale

在处置上下文

后访问实体

Simplified,Lazy Loading的工作原理如下:

  • 每当您从上下文中检索实体时,您实际上会获得一个自动创建的类的子对象,该对象可以覆盖您的virtual导航属性,即代理
  • 每当您访问所述导航属性时,代理将访问数据库并在需要时加载链接的实体。

当然,最后一步只有在实体/代理仍然附加到上下文时才有可能,因此可以查询数据库以检索所述对象。

using( var dbContext = new MyContext() )
{
    dbContext.Configuration.ProxyCreationEnabled = true;
    dbContext.Configuration.LazyLoadingEnabled = true;
    // Note: You can modify or derive from `MyContext` so that this is
    //       done automatically whenever a new `MyContext` is instantiated

    var backpack = dbContext.Backpacks.Where(b=>b.Name!="").FirstOrDefault();

    // This should work
    var firstBook = backpack.Books.FirstOrDefault();
}

// This will probably not, because the context was already disposed
var firstDrink = backpack.Drinks.FirstOrDefault();

我希望这会有所帮助,但如果不是

,请随时提供更多信息

答案 1 :(得分:3)

经过几天的调试,终于找到了问题所在。正如上面提到的那样,您必须启用LazyLoading和ProxyCreating。即使启用了LazyLoading和ProxyCreating,我也遇到了问题。另外,请确保将导航属性声明为virtual,否则EF将无法懒惰地加载实体。

所以我遇到的问题是,由于我的实体没有带有NO参数的公共或受保护的构造函数,因此EF没有创建代理。在创建没有参数的public(在我的情况下受保护)构造函数之后,它工作了。

注意:没有参数的公共/受保护构造函数不会影响预先加载。

Here is a link that explains the requirements for the LazyLoading

答案 2 :(得分:1)

使用Include()方法实现了预先加载,因此您使用Include("Books")强制进行预先加载。

改变这个:

dbContext.Backpacks.Where(b=>b.Name!="").Include("Books").FirstOrDefault()

到此:

dbContext.Backpacks.Where(b=>b.Name!="").FirstOrDefault()

您现在应该看到Books不再被急切加载。

<强>参考:

  1. http://www.entityframeworktutorial.net/EntityFramework4.3/eager-loading-with-dbcontext.aspx
  2. https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx

答案 3 :(得分:0)

我必须使用.NET Core 3.1和Microsoft.EntityFrameworkCore 3.1.5 ...

1)添加Microsoft.EntityFrameworkCore.Proxies NuGet程序包

enter image description here

2)将DbContext配置为UseLazyLoadingProxies(在Startup.cs中)

public void ConfigureServices(IServiceCollection services)
{
   ...
    services.AddDbContext<DataContext>(optionsBuilder =>
    {
        optionsBuilder
            .UseLazyLoadingProxies() // <--- You need this bit
            .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
    });
   ...
}

3)将所有适当的属性(您要延迟加载的属性)标记为virtual

public class MyEntity 
{
    public virtual OtherEntity? { get; set; }  // Lazy loaded coz `virtual`

    public ICollection<OtherEntity> { get; set; }  // NOT lazy loaded coz not `virtual`
}