使用Entity Framework Core從Newtonsoft JsonSerializer自我引用循環

asp.net-core-mvc c# devextreme entity-framework-core json.net

我遇到了錯誤:

JsonSerializationException:為類型為“Project.Models.Subject”的屬性“Subject”檢測到自引用循環。路徑'數據[0]。總計'。

當我使用由IEnumerable<Subject>模型填充的dataGrid加載View時,會發生這種情況。 Grid是一個綁定到View模型的DevExtreme DataGrid,如下所示:

@(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中填充的,該控制器使用此功能從存儲庫中提取數據:

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

Subject表與Totals具有1:1的關係,Totals具有對Subject的外鍵引用。項目中的模型看起來像這樣(從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方法:

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

我從這個答案得到了: https//stackoverflow.com/a/40501464/7897176

但是,這不能解決問題,並且在加載涉及主題的視圖時仍會導致錯誤。將[JsonIgnore]添加到Totals的Subject屬性可以解決問題,但我不想將其添加到模型中的每個子屬性中,並且每當我從db更新模型時都必須重做它。

一般承認的答案

JSON序列化期間自引用循環的問題與EFCore加載相關數據( docs )的方式有關。加載集合時,可能會或可能不會自動填充相關實體,具體取決於先前是否已加載這些對象。它被稱為導航屬性的自動修復 。或者,可以通過.Include()急切加載它們。

每當您獲得要序列化的實體的自引用圖時,有幾個選項:

  • Newtonsoft.Json.ReferenceLoopHandling.Ignore官方推薦 )。如果自我引用發生在層次結構的深處,它仍然可以導致序列化過多的數據。

  • 導航屬性的[JsonIgnore]屬性。如您所述,重新生成模型類時,屬性會消失。因此,它們的使用可能是不方便的。

  • (最佳選擇)預先選擇屬性的子集:

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

    該方法具有僅序列化所需數據的優點。它與DevExtreme的DataSourceLoader兼容:

    return DataSourceLoader.Load(minimallyNecessarySet, loadOptions);
    


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow