【问题标题】:Only eager load navigation properties I explicitly specify只有我明确指定的急切加载导航属性
【发布时间】:2017-03-16 12:56:49
【问题描述】:

瘦子:在将​​我的图形序列化为 JSON 时,由于循环引用问题,我正在尝试禁用导航属性的即时加载。

我有这些课程:

public class Province 
{
    public ICollection<City> Cities { get; set; }
}

public class City 
{
    public Province Province { get; set; }
}

当我想要获取城市集合时,我会提供以下内容:

set.Include(e => e.City.Province);

最终发生的事情是它按预期将所有内容加载到省份,但它也加载了所有省份的城市。这会导致序列化期间出现循环引用,因为在我的基础集合中返回的相同引用也存在于各省。

我对显式加载的期望是City.Province 将有一个引用,但City.Province.Cities 将为空。相反,.Cities 急切地加载了数据,我不希望这样。

我最终尝试的是用这个来保留引用:

config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling =
    Newtonsoft.Json.PreserveReferencesHandling.Objects;

这允许我的 JSON 序列化,但现在客户端必须处理像 [{$id:1, name:"SomeCity"}, {$ref:1}] 这样的数组。我想找到重建引用的方法,但决定最好完全避免循环引用。

【问题讨论】:

  • 您是否尝试过在上下文中实际禁用延迟加载?
  • @DavidG 我没想到。我正在尝试禁用急切加载,而不是延迟加载。我知道在序列化过程中不会发生这种延迟加载,因为一旦对象从 DbContext 中出来,它们就会被完全填充。不过,我会调查一下,看看它是否有任何作用
  • 显式指定某些内容并不会阻止进一步的延迟加载,它只会修改发送到数据库的初始查询。
  • @DavidG 正如预期的那样,使用dbContext.Configuration.LazyLoadingEnabled = false 禁用延迟加载并没有改变任何东西。此外,我们不处理延迟加载。急切的加载就是问题所在。我不希望它急于加载我没有提供特定包含的任何属性。

标签: entity-framework entity-framework-6 eager-loading


【解决方案1】:

设置实体框架,以便所有引用自动了解彼此。您可以尝试几件事。

  1. 使用 .AsNoTracking()(就在 .ToList() 之前)。它可能最终会加载所有级别的所有数据,但我认为它会删除循环引用。

  2. 创建 Dtos/Model 来存储您想要的关系并以这种方式映射到它。

  3. 在序列化之前,您必须遍历子级并将父级引用直接设置为 null。然后它会破坏循环数据。

【讨论】:

  • #3 实际上是我最终作为缓解循环引用问题的临时解决方案所做的。对于#1,我不是要简单地掩盖症状,而是要找到解决核心问题本身的方法。 #2:额外的工作太多。最后,我认为必须有一种方法告诉 EF 防止急切加载特定的导航字段。当然,工程团队知道开发人员会有像我这样结构的类(我的省类实际上有一个 Country 属性,而我的 Country 类有一个 Provinces 集合,所以当我一直包含 Country 时,情况更糟)
  • 第四个选项,取决于数据的使用方式,是在最顶层(即控制器)使用匿名类。除了返回 Json(results) 你可以做 Json(from a in results select new { ... }) 来获得你想要返回的确切数据,然后你就不需要担心任何循环引用。
  • 与清空属性相同。只掩盖症状,不解决问题。此外,当您使用匿名对象时,您必须克隆或精心选择您需要的内容,否则您最终只会复制引用
  • 我知道的唯一其他选择是您可以使用 [NotMapped] 属性(或在流利的 api 中忽略)标记这些父属性,但这会导致无法上链以后如果你需要的话。我相信大多数人创建 Dtos 是为了从实体中返回映射,因为您通常不希望将数据库直接暴露给外部世界。
猜你喜欢
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多