预先加载包括使用UseLazyLoad代理



我正在像这样创建数据库连接:

protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
{
optionbuilder.UseLazyLoadingProxies().UseSqlite(@"Data Source=Data.db");
}

我正在尝试访问这样的对象:

public static User GetProfile(int uid)
{
using (Db db = new Db())
{
return db.Users.Include(x => x.Settings).FirstOrDefault(x => x.UserId == uid);
}
}

用户对象如下所示:

public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Name { get; set; }
public DateTime? LastUsed{ get; set; }
public virtual Setting Settings { get; set; }
}

但是在访问Users.Settings时,它会抛出以下错误:

'为警告生成错误 'Microsoft.EntityFrameworkCore.Infrastructure.LazyLoadOnDisposedContextWarning: 尝试延迟加载导航属性"设置" 实体类型"UserProxy"在释放关联的 DbContext 之后。 可以通过传递事件 ID 来抑制或记录此异常 'CoreEventId.LazyLoadOnDisposedContextWarning' 到 'DbContext.OnConfiguring' 中的 'ConfigureWarnings' 方法或 'AddDbContext'。

我理解这意味着什么,但它违背了我对包含以及它如何导致急切加载的理解。

我的理解是,当使用include并通过调用 eager load 来显式访问对象时FirstOrDefault立即填充相关对象,而无需保持打开状态的数据库连接; 但显然,情况并非如此。

在不需要数据库保持打开状态的情况下执行此操作的正确方法是什么?

Auther V,一位致力于EFC的开发人员已经确认这是一个错误。

https://github.com/aspnet/EntityFrameworkCore/issues/15170

有关此更改的文档

它在EF Core 3.0.0 RC4中已修复,但在撰写本文时,在公共领域不可用。我个人不建议使用 RC4,因为它仍在开发中,不太适合通用或生产用途。

现在,您可以像这样抑制错误:

protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
{
optionbuilder.UseSqlite(@"Data Source=Data.db").UseLazyLoadingProxies();
optionbuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning));
}

optionbuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning));行是您需要的。

但请注意,当尝试对关闭的 DBContext 实例进行对象遍历时,任何不当使用延迟加载也会被忽略,提供空变体。

最新更新