实体框架-通过虚拟关键字的延迟加载-检测循环引用

时间:2018-09-21 12:29:48

标签: c# .net entity-framework entity-framework-6

Entity Framework延迟加载集合(如果集合用虚拟关键字标记(用于代理))并且在上下文上启用了延迟加载。例如:

public class Entity()
{
    public virtual ICollection<OtherEntity> OtherEntities { get; set; }
}

即使从数据库中获取相关信息的方法对此实体没有包含,EF也将加载OtherEntities。

了解到序列化会导致问题,并将大量不必要的数据加载到创建的结果中,从而覆盖序列化器中的内容,因此我开始删除虚拟关键字并在相关的存储库中添加包含,但是我们仍然倾向于陷入可怕的循环引用问题一次创建一次结果。一些实体内部可能有数十个集合,因此它很难调试,甚至不会引发异常,而只是在消耗越来越多内存的实体之间循环。我被迫手动追踪它开始循环的地方。这是耗时的并且非常糟糕。知道是否有更好的方法来本地化导致序列化问题的Collection吗?

与99%的.net项目一样,我们正在使用newtonsoft进行序列化。

1 个答案:

答案 0 :(得分:-1)

首先,您可以通过配置禁用延迟加载,并在需要使用延迟加载的情况下保留virtual属性:

dbContext.Configuration.LazyLoadingEnabled = false;

第二,循环引用不是唯一的延迟加载问题-如果从数据库中分别检索其跟踪属性/集合的内容,EF会钩住任何被跟踪的实体(这就是为什么您偶尔会遇到“ '的问题,删除了所有virtual关键字之后。

您可以将循环引用的一侧配置为不序列化(例如ScriptIgnoreAttribute),但这将始终阻止序列化(例如,如果您忽略OtherEntity.Entity,以便可以序列化{{1} }没有循环引用的对象图,它将在序列化Entity对象图时阻止您包含OtherEntity.Entity

另一种选择是创建一个单独的视图模型(或数据传输对象)以控制数据的序列化方式。

然后是序列化格式规范,它们仅在明确要求的情况下才包含参考数据(例如ODataJSON-API),从而完全避免了该问题。 JSON-API在整个响应中还只包含每个对象一次。