はじめに
EFCore で公式のチュートリアルにしたがって多対多のリレーションを実装している際にうまくデータを読みだせない現象が発生しました。
その際に表示されたエラーメッセージは下記です。
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.
環境
- Windows11
- .net
- ASP.net Core Web API
- EfCore
コード
読み出し部分
[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public ActionResult<User> Get(int id)
{
var user = _context.Users
.Include(u => u.Skills)
.FirstOrDefault(o => o.Id == id);
if (user == null)
{
return NotFound();
}
return user;
}
なんの変哲もない GetAPI です。
モデル
User.cs
public class User
{
[Required]
public int Id { get; set; }
[Required]
public string Username { get; set; } = string.Empty;
[Required]
public string Description { get; set; } = string.Empty;
public List<Skill> Skills { get; } = [];
}
Skill.cs
public class Skill
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public List<User> Users { get; } = [];
}
原因
お互いが参照しあっていたため循環参照になりシリアル化の際にエラーが発生していました。
同じような現象は多く発生しているようで、下記のような質問を StackOverflow で見つけました。
修正方法
シリアル化の際にお互いを参照している部分のうち、片方のプロパティを無視するように設定を変更しました。
Skill.cs
+using System.Text.Json.Serialization;
public class Skill
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
+ [JsonIgnore]
public List<User> Users { get; } = [];
}
[JsonIgnore]
のアノテーションを追加する事でシリアルの際に無視されるようになります。
おわりに
EFCore は使いこなすと開発の強い助けになるため、今後も使っていきたいです。
この記事が皆様のコーディングライフの助けになれば幸いです。
参考