簡體   English   中英

如何解決 System.Text.Json.JsonException:在實體框架中檢測到可能的 object 循環?

[英]How to resolve System.Text.Json.JsonException: A possible object cycle was detected in Entity Framework?

我有一個帶有表/數據的數據庫,所以我使用了 db first 方法,使用以下命令來搭建模型:

dotnet ef dbcontext scaffold "Server=.;Database=MyDb;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o Models

這已經生成了與我的表相對應的DbContext和幾個 model 類。 此問題僅涉及 2 個模型,因此我提供以下代碼:

個人.cs:

using System;
using System.Collections.Generic;

namespace MyApp.Models
{
    public partial class Person
    {
        public Person()
        {
            Profiles= new HashSet<Profile>();
        }

        public int Id { get; set; }
        public string Email { get; set; } = null!;
        public string Password { get; set; } = null!;

        public virtual ICollection<Profile> Profiles { get; set; }
    }
}

個人資料.cs:

using System;
using System.Collections.Generic;

namespace MyApp.Models
{
    public partial class Profile
    {
        public Profile()
        {
            Sales = new HashSet<Sale>();
        }

        public int Id { get; set; }
        public int PersonId { get; set; }
        public string ProfileName { get; set; } = null!;

        public virtual Person Person { get; set; } = null!;
        public virtual ICollection<Sale> Sales { get; set; }
    }
}

在 controller 我正在嘗試以下查詢:

var person = await _context.Person
                           .AsNoTracking()
                           .Where(c => c.Email == 'test@testmail.com')
                           .ToListAsync();

這行得通。 但是以下查詢會引發錯誤:

var profiles = await _context.Person
                             .AsNoTracking()
                             .Where(c => c.Email == 'test@testmail.com')
                             .Include(c => c.Profiles)
                             .ToListAsync();

錯誤:

System.Text.Json.JsonException:檢測到可能的 object 循環。 這可能是由於循環或 object 深度大於最大允許深度 32。考慮在 JsonSerializerOptions 上使用 ReferenceHandler.Preserve 以支持循環。

小路:
$.Profiles.Person.Profiles.Person.Profiles.PersonProfiles.PersonProfiles.PersonProfiles.PersonProfiles.PersonProfiles.PersonProfiles.Person.Id。

在 System.Text.Json.ThrowHelper.ThrowJsonException_SerializerCycleDetected(Int32 maxDepth)
at System.Text.Json.Serialization.JsonConverter 1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.Serialization.Metadata.JsonPropertyInfo 1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer )

你得到這個的原因是你正在序列化一個有循環的 object 圖,這是一個典型的 EF DB 實體圖

想象一下,您有一個擁有一個 Profile 的 Person,並且該 Profile 有一個 Person(返回父 Person 的鏈接)

可以編寫 C# 代碼,如:

myPerson.Profiles.First().Person.Profiles.First().Person.Profiles.First().Person.Profiles.First().Person.Profiles.First().Person..

你可以永遠這樣 go ..

..這就是 json 序列化程序在嘗試序列化每個配置文件的每個屬性時也在做的事情

你有幾個選擇..

  • 您可以在序列化之前修改圖表:將每個 Profile 的 Person(或任何級別 N 屬性是第一個鏈接回早期 Nx 的屬性)設置為 null 以停止循環

  • 您可以序列化沒有循環的 object 圖,例如在序列化之前將您的 EF 實體 map 到的一組 DTO

  • 您可以告訴 Newtonsoft 觀看引用而不設置它之前看到的任何內容:

string json = JsonConvert.SerializeObject(joe, Formatting.Indented, new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});

我說,大多數人會避免看到這種情況,因為他們選擇了選項 2; 通常我們不會序列化我們的數據庫實體,我們有一組專門為我們的前端設計的類,它們可能看起來不同等; 很少有系統的前端完全且准確地需要看起來與數據庫建模完全相同的數據對象。 如果那些以前端為中心的對象沒有周期(一個人可能有一個配置文件列表,但沒有必要將配置文件鏈接回來,因為在繪制 hi 時它使用得太低了)它們不會導致這個問題。

小心選項1; 如果在將圖形修改為對序列化程序友好之后調用上下文中的保存(出於任何原因),您最終可能會斷開數據庫中的關系。 3有點雜亂無章,可以解決由於沒有完成2而導致的問題,但2是go的更多努力

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM