1

I have four models auto generated by Entity Framework Core (2.1.4) (using scaffold) that are related between themselves.

public partial class Run
{
    public int Id { get; set; }
    public int RunCarId { get; set; }
    public int RunExtraInfoId { get; set; }
    ...
    public RunExtraInfo RunExtraInfo{ get; set; }
    public RunCar RunCar{ get; set; }
    public ICollection<Weighing> Weighings{ get; set; }
}

public partial class RunExtraInfo
{
    public int Id { get; set; }
    ...
    public ICollection<CorridaCt> Runs { get; set; }
}

public partial class RunCar
{
    public int Id { get; set; }
    ...
    public Run Run{ get; set; }
}

public partial class Weighing
{
    public int Id { get; set; }
    public int RunId { get; set; }
    ...
    public Run Run{ get; set; }
}

But whenever I include all info I need on Run, all other relations are loaded to the entities, making it very recursive.

Example:

var runs = ContextSQL.Runs
                     .Include(c => c.RunExtraInfo)
                     .Include(c => c.RunCar)
                     .Include(c => c.Weighings)
                     .ToList();
return runs;

Generates:

[
  {
    id: 0,
    ...
    runExtraInfo: {
      id: 0,
      ...
      runs: [
        {
          id: 0,
          runExtraInfo: {id: 0 runs: [...]},
          runCar: {id: 0, runs: [...]}
        }
      ]
    },
    runcar: {
      id: 0,
      runs: [
        {id: 0, runExtraInfo: [...], runs: [...]}
      ]
    }
  }
]

I thought entity was supposed to include the relations only if we included them explicitly with Include(), am I wrong?

How can I solve this problem?

2
  • 1
    An option is to use the attribute [Script Ignore] on places where you want to prevent recursion. Commented Dec 30, 2021 at 20:01
  • Shortly, you cannot stop EF Core doing that because it is by design. If you have serialization issues, use separated classes or serialization options/attributes. Commented Dec 30, 2021 at 20:09

1 Answer 1

2

To avoid it, you need to use explicit loading as described here Explicit Loading in Entity Framework core.

Or you need to return only the fields you need, instead of the database models:

var runs = ContextSQL.Runs
    .Include(c => c.RunExtraInfo)
    .Include(c => c.RunCar)
    .Include(c => c.Weighings)
    .Select(c => new { c.Id, c.RunExtraInfo, c.RunCar, c.Weighings })
    .ToList();
return runs;

Or instead of using an anonymous object, you can use DTO's that contains only the data you want (where you remove the fields and circular references you don't want):

var runs = ContextSQL.Runs
    .Include(c => c.RunExtraInfo)
    .Include(c => c.RunCar)
    .Include(c => c.Weighings)
    .Select(c => new RunDTO(c))
    .ToList();
return runs;

See (extern microsoft link) Create Data Transfer Objects (DTOs).

As mentioned in the comments of your question, you can also use the [JsonIgnore] attribute, for fields you don't want converted to Json, but you may prefer to use DTO's instead.

Sign up to request clarification or add additional context in comments.

1 Comment

I went with the DTO option, works like a charm, thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.