循環エラー ASP.Net Core6 EntityFramework

循環エラー 発生

ASP.Net Core6とEntityFramework6を使用していると 循環エラー が発生した。

以下のような相互参照モデルがあった場合

Town.cs

using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace BackEnd.Data.Model {
    /// <summary>
    /// 町・群
    /// </summary>
    [Index(nameof(Name))]
    [Index(nameof(Lat))]
    [Index(nameof(Lon))]
    public class Town {

        [Key]
        [Required]
        public int Id { get; set; }

        /// <summary>
        /// 町・群名
        /// </summary>
        public string Name { get; set; } = null!;

        /// <summary>
        /// 緯度
        /// </summary>
        [Column(TypeName ="decimal(7,4)")]
        public decimal Lat { get; set; }

        /// <summary>
        /// 経度
        /// </summary>
        [Column(TypeName ="decimal(7,4)")]
        public decimal Lon { get; set; }

        /// <summary>
        /// 郵便番号
        /// </summary>
        public string PostCode { get; set; } = null!;

        /// <summary>
        /// 市ID
        /// </summary>
        [ForeignKey(nameof(City))]
        public int CityId { get; set; }

        /// <summary>
        /// 市
        /// </summary>
        public City? City { get; set; } = null!;
    }
}

City.cs

using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace BackEnd.Data.Model {
    /// <summary>
    /// 市
    /// </summary>
    [Index(nameof(Name))]
    public class City {

        [Key]
        [Required]
        public int Id { get; set; }

        /// <summary>
        /// 市名
        /// </summary>
        public string Name { get; set; } = null!;

        /// <summary>
        /// 県ID
        /// </summary>
        [ForeignKey(nameof(Province))]
        public int ProvinceId { get; set; }

        /// <summary>
        /// 県
        /// </summary>
        public Province? Province { get; set; } = null!;

        /// <summary>
        /// 町・群 リスト
        /// </summary>
        public ICollection<Town>? Towns { get; set; } = null!;
    }
}

これらのモデルを取得し、コントローラーからTownのリストを取得する際に以下のような 循環エラー が発生する。

        /// <summary>
        /// 町・群のリストを取得する
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ActionResult<List<Town>>> GetTowns() {
            return await _context.Towns.AsNoTracking().Include(t => t.City).ToListAsync();
        }
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.

原因

公式サイトいわく…

EF Core ではナビゲーション プロパティの修復が自動的に行われるので、最終的にオブジェクト グラフの循環が生じる可能性があります。 たとえば、ブログとその関連する投稿を読み込むと、投稿のコレクションを参照するブログ オブジェクトになります。 これらの各投稿には元のブログへの参照が含まれることになります。

一部のシリアル化フレームワークでは、このような循環は許可されていません。 たとえば、Json.NET では、循環が発生した場合に次の例外がスローされます。

関連データとシリアル化

対処法

Program.csに以下の記述を追加すると解決した。

builder.Services.AddControllers().AddJsonOptions(options => {
    options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
});

「循環エラー ASP.Net Core6 EntityFramework」への1件のフィードバック

  1. 同様のエラーが出たため、対処法のみ実装したところ解決しました!
    助かりました。有益な情報、ありがとうございます。

    返信

コメントする