使用UseLazyLoadingProxies可以进行预先加载

时间:2019-03-27 03:01:58

标签: c# entity-framework asp.net-core lazy-loading ef-core-2.2

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

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.LazyLoadOnDisposedContext警告:   尝试将导航属性“设置”延迟加载到   处置关联的DbContext之后的实体类型'UserProxy'。”。   可以通过传递事件ID来抑制或记录此异常   “ CoreEventId.LazyLoadOnDisposedContextWarning”到   'DbContext.OnConfiguring'中的'ConfigureWarnings'方法或   “ AddDbContext”。

我理解这是什么意思,但这与我对include的理解以及它如何引起热切的加载背道而驰。

我的理解是,在使用include并通过调用FirstOrDefault显式访问对象时,急切地加载要立即填充的相关对象,而无需保持db连接的打开状态;但显然并非如此。

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

1 个答案:

答案 0 :(得分:1)

作者V,从事EFC的开发人员已确认这是一个错误。

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

Documentation about this change

它在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实例进行对象事务传输时,如果提供了无效的变体,则也将忽略延迟加载的任何不当使用。