避免或控制Entity Framework Core中的循环引用 [英] Avoid or control circular references in Entity Framework Core
问题描述
我真的已经完成了,但是至少我想知道发生了什么.我们开始:
I really am done with this, but at least I want to know what's going on. Here we go:
我的项目是一个具有Code First Entity Framework Core和Angular前端的ASP.NET Core Web应用程序.
My project is an ASP.NET Core Web Application with Code First Entity Framework Core and an Angular frontend.
我想控制何时加载引用的对象.它们可能很有用,但它们也可以创建在前端具有内部错误的循环引用.(JSON会无限长.)
I want to control when to load referenced objects. They can be useful, but they can also create circular references with internal errors on the frontend. (JSON would be infinitely long.)
型号:
class Book {
public virtual ICollection<Page> Pages { get; set; }
...simple properties
}
class Page {
public virtual Book Book { get; set; }
...simple properties
}
在此示例中, books 中的每本图书都会有一个空/空的 Pages 列表.
In this example, every book from books will have an empty/null Pages list.
using (var context = new MoneyStatsContext())
{
var books = context.Books.Where(rule => rule.State == 1).ToList();
}
在此示例中, Pages 列表不为空,并且每个 Page 都将设置它的 Book 属性.这样就创建了一个循环引用.
In this example, the Pages lists are not null, and every Page will have it's Book property set. Thus creating a circular reference.
using (var context = new MoneyStatsContext())
{
var books = context.Books.Where(rule => rule.State == 1).Include(x => x.Pages).ToList();
}
如何避免循环引用?除了创建新模型并手动指定每个属性外,我真的没有别的选择吗?
How do I avoid the circular reference? Do I really have no other (simpler) choice than creating a new model and manually specifying each property?
.Select(new Book() {
...setting each property by hand
}
我发现的无效解决方案:
- 尝试将其设置为false和true.似乎没有任何改变.
public MyContext()
{
this.ChangeTracker.LazyLoadingEnabled = false;
}
- 试图在Startup.cs中指定它,但是 options 没有SerializerSettings属性.
- Tried specifying this in Startup.cs, but options doesn't have a SerializerSettings property.
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
任何帮助将不胜感激.预先感谢.
Any help would be appreciated. Thanks in advance.
推荐答案
假设您使用的是最新,最出色的ASP .NET Core 3.1和 System.Text.Json
,来处理引用循环,您将需要切换到返回"状态到 Newtonsoft.Json
(尽管值得一提的是 System.Text.Json
应该更快.另外,对引用循环处理的支持是 @Eric J在评论中写道):
Assuming you are using the latest and greatest ASP .NET Core 3.1 with System.Text.Json
, to handle reference loops you will need to switch "back" to Newtonsoft.Json
(though it worth mentioning that System.Text.Json
should be faster. Also support for reference loops handling is coming, as @Eric J. wrote in comments):
services.AddControllers()
.AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)
至于EF创建参考循环-它被称为 relationship fixup
,您对此无能为力(请参阅
As for EF creating reference loops - it is called relationship fixup
and you can't do a lot about it (see this answer). AsNoTracking
can help a little bit (but not in case of Include
). My personal approach is to return DTO's from endpoints and not entites directly.
UPD
In .NET 5.0 ReferenceHandler
is introduced, so next should do the trick:
services.AddControllersWithViews()
.AddJsonOptions(options =>
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve)
这篇关于避免或控制Entity Framework Core中的循环引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!