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

C# 实体框架-通过虚拟关键字延迟加载-检测循环引用,c#,.net,entity-framework,entity-framework-6,C#,.net,Entity Framework,Entity Framework 6,如果使用虚拟关键字标记集合以进行代理,并且在上下文上启用了延迟加载,则实体框架将在后台延迟加载集合。例如: public class Entity() { public virtual ICollection<OtherEntity> OtherEntities { get; set; } } EF将加载其他实体,即使从数据库获取该实体的相关方法没有包含该实体 知道它会导致序列化问题,并且会将大量不必要的数据加载到创建的结果中,覆盖了序列化程序中的内容,我开始删除虚拟关键字

如果使用虚拟关键字标记集合以进行代理,并且在上下文上启用了延迟加载,则实体框架将在后台延迟加载集合。例如:

public class Entity()
{
    public virtual ICollection<OtherEntity> OtherEntities { get; set; }
}
EF将加载其他实体,即使从数据库获取该实体的相关方法没有包含该实体

知道它会导致序列化问题,并且会将大量不必要的数据加载到创建的结果中,覆盖了序列化程序中的内容,我开始删除虚拟关键字并在相关存储库中添加include,但我们仍然倾向于每隔一段时间就在创建的结果中突然出现可怕的循环引用问题。有些实体内部可能有几十个集合,因此很难调试,甚至不会引发异常,只是在实体之间循环,消耗越来越多的内存。我被迫手动追踪它开始骑车的地方。这既费时又令人毛骨悚然。知道有没有更好的方法来本地化导致序列化问题的集合吗


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

首先,您可以通过配置禁用延迟加载,并在需要使用延迟加载时不使用虚拟属性:

dbContext.Configuration.LazyLoadingEnabled = false;
其次,延迟加载不是循环引用的唯一问题-如果从数据库中单独检索到任何跟踪实体的nav属性/集合的内容,EF将连接这些实体,这就是为什么在删除所有虚拟关键字后会遇到“偶尔”问题的原因

您可以将循环引用的一侧配置为不序列化,例如ScriptIgnoreAttribute,但这将始终阻止序列化,例如,如果您忽略OtherEntity.Entity,则可以序列化没有循环引用的实体对象图,序列化OtherEntity对象图时,它将阻止您包括OtherEntity.Entity

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

还有一些序列化格式规范,这些规范通过仅在特别要求的情况下包括引用数据(例如和)来完全避免问题。JSON-API在整个响应中只包含每个对象一次