Avoid or control circular references in Entity Framework Core

别说谁变了你拦得住时间么 提交于 2021-02-05 11:15:12

问题


I really am done with this, but at least I want to know what's going on. Here we go:

My project is an ASP.NET Core Web Application with Code First Entity Framework Core and an Angular frontend.

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.)

Models:

class Book {
   public virtual ICollection<Page> Pages { get; set; }
   ...simple properties
}

class Page {
   public virtual Book Book { get; set; }
   ...simple properties
}

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();
}

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
}

Not-working-solutions I've found:

  • Tried setting this false and true. Doesn't seem to change anything.
public MyContext()
{
   this.ChangeTracker.LazyLoadingEnabled = false;
}

  • 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.


回答1:


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)

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)


来源:https://stackoverflow.com/questions/62985907/avoid-or-control-circular-references-in-entity-framework-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!