我有一些类似下面的模型:
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:
但是一旦我要求 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);
如下所示:
然后突变体的OriginalCode
字段不为空:
是什么原因以及如何解决?
答案 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文档中的示例进行了解释。