使用实体框架核心从Newtonsoft JsonSerializer进行自引用循环 [英] Self referencing loop from Newtonsoft JsonSerializer using Entity Framework Core

查看:258
本文介绍了使用实体框架核心从Newtonsoft JsonSerializer进行自引用循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了错误:

JsonSerializationException:检测到以下情况的自引用循环 属性"Subject",类型为"Project.Models.Subject".小路 数据[0].总计".

JsonSerializationException: Self referencing loop detected for property 'Subject' with type 'Project.Models.Subject'. Path 'data[0].Totals'.

当我加载由IEnumerable<Subject>模型填充的dataGrid的View时,会发生这种情况.网格是绑定到View模型的DevExtreme DataGrid,如下所示:

It occurs when I load a View with a dataGrid populated by an IEnumerable<Subject> model. The Grid is a DevExtreme DataGrid bound to the View's model like this:

@(Html.DevExtreme().DataGrid()
    .DataSource(Model)
    .Paging(paging =>
    {
        paging.Enabled(true);
        paging.PageIndex(0);
        paging.PageSize(20);
    })
    .Columns(columns =>
    {
        columns.Add().DataField("SubjectId");
        ... other fields
    })
)

其中哪个是从Controller填充的,该Controller使用以下功能从存储库中提取数据:

Which is populated from a Controller that pulls data from a Repository with this function:

public async Task<IEnumerable<Subject>> GetSubjectsAsync()
        {
            return await _context.Subject.ToListAsync();
        }

主题"表与总计"具有1:1关系,总计"具有对主题"的外键引用.项目中的模型如下所示(从Scaffold-DbContext生成):

The Subject table has a 1:1 relationship with Totals with Totals having a foreign key reference to Subject. The Models in the project look like this (generated from Scaffold-DbContext):

public partial class Subject
    {
        public Guid SubjectId { get; set; }
        public virtual Totals Totals { get; set; }
    }

public partial class Totals
    {
        public Guid TotalsId { get; set; }
        public virtual Subject Subject { get; set; }
    }

由于2个对象互相引用,因此在序列化时会导致循环.为了解决这个问题,我将此配置添加到了Startup.ConfigureServices方法中:

Since the 2 objects reference eachother it causes a loop when serializing it. To correct this I added this config to my Startup.ConfigureServices method:

services.AddMvc()
                .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

我从这个答案中得到了什么: https://stackoverflow.com/a/40501464/7897176

Which I got from this answer: https://stackoverflow.com/a/40501464/7897176

但是,这不能解决问题,并且在加载涉及主题的视图时仍会导致错误.将[JsonIgnore]添加到Totals的Subject属性可以解决此问题,但是我不想将其添加到模型中的每个子属性中,并且每次从数据库更新模型时都不必重做.

However this doesn't fix the problem and its still causing an error when I load a view that involves Subjects. Adding [JsonIgnore] to the Subject property of Totals fixes the problem, but I don't want to have to add that to every child property in my models and have to redo it whenever I update my models from the db.

推荐答案

JSON序列化期间的自引用循环问题与EFCore如何加载相关数据有关(

The problem of self-referencing loops during JSON serialization is connected to how EFCore loads related data (docs). When you load a collection, related entities may or may not be automatically populated depending on whether or not those object have been previously loaded. It's called automatic fix-up of navigation properties. Alternatively, they may be eagerly loaded via .Include().

每当获得要序列化的实体的自引用图时,就会有以下几种选择:

Whenever you get a self-referencing graph of entities to be serialized, there are several options:

  • Newtonsoft.Json.ReferenceLoopHandling.Ignore (officially recommended). It works but still can result in serializing excessive data if self-reference occurs deep in the hierarchy.

[JsonIgnore]属性.如您所述,当重新生成模型类时,属性消失.因此,它们的使用可能很不方便.

[JsonIgnore] attribute on navigation properties. As you noted, attributes disappear when model classes are regenerated. Thus, their use can be inconvenient.

(最佳选择):预先选择一部分属性:

(Best choice) Pre-select a subset of properties:

var minimallyNecessarySet= _nwind.Products.Select(p => new {
    p.ProductID,
    p.ProductName,
    p.UnitPrice,
    p.CategoryID
});

return minimallyNecessarySet.ToList();

此方法的优点是仅序列化所需的数据.与DevExtreme的DataSourceLoader:

This approach has the advantage of serializing only required data. It's compatible with DevExtreme's DataSourceLoader:

return DataSourceLoader.Load(minimallyNecessarySet, loadOptions);

这篇关于使用实体框架核心从Newtonsoft JsonSerializer进行自引用循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆