c# - 当我尝试使用 .Include() 进行预加载时,EF Core 是延迟加载

标签 c# entity-framework-core ef-core-2.2

我正在使用 EF Core 2.2.6(数据库优先),似乎只是启用延迟加载让我无法进行预加载。启用延迟加载是否会排除以任何容量使用预加载?

namespace Example.Models
{
    public class Lead
    {
        public int Id { get; set; }
        public LeadOrganization LeadOrganization { get; set; }

        public Lead(ExampleContext.Data.Lead dbLead)
        {
            Id = dbLead.Id;
            LeadOrganization = new LeadOrganization(dbLead.LeadOrganization);
        }

        public static Lead GetLead(int id)
        {
            using (var db = new ExampleContext())
            {
                var dbLead = db.Leads
                    .Include(l => l.LeadOrganization)
                        .ThenInclude(lo => lo.LeadOrganizationAddresses)
                            .ThenInclude(loa => loa.AddressType)
                    .FirstOrDefault(l => l.Id== id);

                return new Lead(dbLead);
            }
        }
    }
}
namespace Example.Models
{
    public class LeadOrganization
    {
        public IEnumerable<LeadOrganizationAddress> Addresses { get; set; }

        public LeadOrganization(ExampleContext.Data.LeadOrganization dbLeadOrganization)
        {
            Addresses = dbLeadOrganization.LeadOrganizationAddresses.Select(loa => new LeadOrganizationAddress(loa));
        }
    }
}
namespace Example.Models
{
    public class LeadOrganizationAddress
    {
        public AddressType AddressType { get; set; }

        public LeadOrganizationAddress(ExampleContext.Data.LeadOrganizationAddress dbLeadOrganizationAddress)
        {
            AddressType = new AddressType(dbLeadOrganizationAddress.AddressType);
        }
    }
}
namespace Example.Models
{
    public class AddressType
    {
        public short Id { get; set; }

        public AddressType(ExampleContext.Data.AddressType dbAddressType)
        {
            Id = dbAddressType.Id;
        }
    }
}

ExampleContext.Data 命名空间包含 EF 从数据库生成的分部类。 LeadLeadOrganizationLeadOrganizationAddressAddressType 基本上是 1:1 的类属性,但添加了静态方法(是的,这很奇怪,但这是我必须使用的)。

Lead 有一个 LeadOrganization,LeadOrganization 又至少有一个 LeadOrganizationAddress,而 LeadOrganizationAddress 又有一个 AddressType。

GetLead 调用 Lead 构造函数时,查询中的数据尚未加载,尽管它应该预先加载。这会导致嵌套对象的问题。当它最终到达 LeadOrganizationAddress 构造函数时,DbContext 已被释放,因此无法延迟加载关联的 AddressType

我是不是误解了预加载的全部意义?我认为它会在初始查询时检索所有数据,然后让我毫无问题地将其传递给构造函数。我不需要继续返回数据库并延迟加载任何内容。

如果启用了延迟加载,是否可以简单地不进行预加载?是否有其他解决方法,例如强制它加载任何代理实体?

最佳答案

好的,在调查问题后,EF Core 2.x 延迟加载通过代理实现存在问题。相关的跟踪问题是

问题是导航属性急切加载的,但是LazyLoader不知道在处理时 - 无法安全地访问上下文更改跟踪器并且只是抛出异常.相关代码可见here ,在第一行:

if (_disposed)
{
    Logger.LazyLoadOnDisposedContextWarning(Context, entity, navigationName);
}

当我读到它时,它应该在 EF Core 3.0 中修复,并带有以下“重大更改”- Lazy-loading proxies no longer assume navigation properties are fully loaded .它还部分解释了当前的问题:

Old behavior

Before EF Core 3.0, once a DbContext was disposed there was no way of knowing if a given navigation property on an entity obtained from that context was fully loaded or not.

不幸的是,这不能帮助您解决当前的问题。我看到的选项是:

  1. 等待 EF Core 3.0 发布
  2. 不要通过代理使用延迟加载
  3. 关闭 lazy loading on disposed context 警告 - 默认为 Throw,将其更改为 LogIgnore,例如:

    optionsBuilder.ConfigureWarnings(warnings => warnings
        .Log(CoreEventId.LazyLoadOnDisposedContextWarning)
    );
    

关于c# - 当我尝试使用 .Include() 进行预加载时,EF Core 是延迟加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57664047/

相关文章:

c# - MySql、Ninject 和 NHibernate - 已经有一个与此连接关联的打开的 DataReader,必须先将其关闭

c# - 构建 SQL Where 来自委托(delegate)的查询

c# - 为什么我的线程完成后要花这么长时间才能退出?

c# - 什么会导致 DbSet 中的持久化实体分离?

c# - 从.NET core中的IQueryable获取Sqlite SQL语句

c# - 如何直接在浏览器中打开 pdf 文件?

sqlite - 为什么我的 Blazor 服务器应用程序要等待渲染,直到检索到数据,即使使用异步也是如此?

asp.net - INSERT语句与FOREIGN KEY约束冲突

.net-core - 在 MySQL 上调用存储过程时在 EF Core 上发生转换错误(使用 Pomelo)

entity-framework-core - 使用接口(interface)搭建 EF Core 实体