EF Core在直接访问之前返回空关系

时间:2017-02-19 13:03:11

标签: entity-framework-core

我有一些类似下面的模型:

public class Mutant
{
    public long Id { get; set; }
    ...

    // Relations
    public long OriginalCodeId { get; set; }
    public virtual OriginalCode OriginalCode { get; set; }
    public int DifficultyLevelId { get; set; }
    public virtual DifficultyLevel DifficultyLevel { get; set; }
}

public class OriginalCode
{
    public long Id { get; set; }
    ...

    // Relations
    public virtual List<Mutant> Mutants { get; set; }
    public virtual List<OriginalCodeInputParameter> OriginalCodeInputParameters { get; set; }
}

OnModelCreating的{​​{1}}中,我建立了这样的关系:

DBContext

现在当我请求Mutants时,OriginalCode为null:

Null OriginalCode

但是一旦我要求 modelBuilder.Entity<Mutant>() .HasOne(m => m.OriginalCode) .WithMany(oc => oc.Mutants) .HasForeignKey(m => m.OriginalCodeId) .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict); modelBuilder.Entity<Mutant>() .HasOne(m => m.DifficultyLevel) .WithMany(dl => dl.Mutants) .HasForeignKey(m => m.DifficultyLevelId) .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict); 如下所示:

OriginalCodes

然后突变体的OriginalCode字段不为空:

Filled Object

是什么原因以及如何解决?

1 个答案:

答案 0 :(得分:33)

原因在EF Core文档的Loading Related Data部分进行了解释。

第一种行为是因为EF Core目前不支持延迟加载,因此通常您将获得null导航属性,直到您通过急切或显式加载专门加载它们。但是,预期加载部分包含以下内容:

  

提示
  实体框架核心将自动将导航属性修复到先前加载到上下文实例中的任何其他实体。因此,即使您没有明确包含导航属性的数据,如果之前加载了部分或全部相关实体,该属性仍可能会被填充。

解释了为什么导航属性在第二种情况下不为空。

现在,我不确定您要修复哪两种行为,因此会尝试解决这两种问题。

第一种行为可以是&#34;固定&#34;通过使用当前可用的方法之一来加载相关数据,例如预先加载:

var mutants = db.Mutants.Include(m => m.OriginalCode).ToList();

第二种行为是&#34;按设计&#34;并且无法控制。如果你想避免它,请确保使用全新的DbContext实例来执行单个查询以重试所需的数据。

更新:从v2.1开始,EF Core支持Lazy Loading。但是,默认情况下它未启用,因此为了使用它,应标记所有导航属性virtual,安装Microsoft.EntityFrameworkCore.Proxies并通过UseLazyLoadingProxies调用启用它,或者使用{{ 3}} - 两者都用EF Core文档中的示例进行了解释。