Entity Framework 未延迟加载引用和集合属性

Entity Framework is not loading the reference and collection properties lazily

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

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

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

在我的 属性 getter/setter 中,我有一些逻辑会被触发,但我不确定这怎么会是个问题。

预先加载是使用 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

由于手头资料有限,我可以看到以下针对您的问题的解释。

延迟加载或代理创建被禁用

确保启用了延迟加载和代理创建,如果没有后者,前者将无法工作。

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

(详见this SO post

配置上下文后访问实体

简化后的延迟加载是这样的:

  • 每当您从上下文中检索一个实体时,您实际上会得到一个自动创建的 class 子 class 的对象,您期望它会覆盖您的 virtual 导航属性,它是代理.
  • 每当您随后访问所述导航属性时,代理将访问数据库并在需要时加载链接的实体。

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

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();

希望对您有所帮助,如果没有帮助,请随时提供更多信息

调试了几天,终于找到问题所在了。如上所述,您必须启用 LazyLoading 和 ProxyCreating。即使启用了 LazyLoading 和 ProxyCreating,我也遇到了问题。还要确保将导航属性声明为 virtual,否则 EF 将无法延迟加载实体。

所以我遇到的问题是,EF 没有创建代理,因为我的实体没有 public 或没有参数的受保护构造函数。在创建没有参数的 public (在我的例子中是受保护的)构造函数之后它起作用了。

注意: 没有 public/protected 不带参数的构造函数不会影响预先加载。

Here is a link that explains the requirements for the LazyLoading

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

执行的步骤

1) 添加 Microsoft.EntityFrameworkCore.Proxies NuGet 包

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