Efcore: Circular References

Created on 26 Feb 2016  路  7Comments  路  Source: dotnet/efcore

My model is effectively:

public class Project
{
    [Key]
    public Guid ProjectId { get; set; }

    public Guid ClientId { get; set; }
    public virtual Client Client { get; set; }
}

public class Client
{
    [Key]
    public Guid ClientId { get; set; }

    public virtual ICollection<Project> Projects { get; set; } = new List<Project>();
}

Up until I changed to the EntityFrameworkCore, I could fetch Projects with their associated Clients:

DbContext.Projects.Include(p => p.Client);

Since upgrading, I'm getting the error:
Additional information: Self referencing loop detected with type 'Models.Project'. Path 'Client.Projects'.

This should be pretty straight-forward: give me the Projects and their Clients. I don't want the Clients' Projects - else then I could see the issue with the loop.

I've mentioned this here:
https://github.com/aspnet/Mvc/issues/4160

All 7 comments

You probably should serialize a ViewModel that doesn't have reference loop (anyway using DTO is the way to go) and not the entities or setting

services.AddMvc().AddJsonOptions(options => {
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            });

As I commented on the MVC issue.

A lot of developers have the same problem and spend his time.

@Microsoft: Why one don't make the setting ReferenceLoopHandling = ReferenceLoopHandling.Ignore as the default settings of Newtonsoft.Json?

Yes, a default that throws an exception when used might not be the best option... :confused:

@capesean EF will always fix up navigation properties for everything that you bring into memory. So loading projects with their respective clients will always result in the client navigation properties pointing back to projects that are assigned to them (only the ones that are in memory... it won't go and fetch the additional ones from the database unless you tell it to).

What I'm not sure about is why this has only just started failing for you. EF has always had this behavior (right from its first release). It was missing from some of the early EF7 betas, but it's been there for the last few pre-releases. Was it RC1 that you upgraded from?

Hi Rowan

I've been using RC2 and it's been working like a dream until I changed recently to EFC1.0 - I'm not sure what the possibility that I've been using an early EF7 build is. But just to clarify: I do use DTOs and I also have been using .Include when I specifically want the related entity loaded. So typically I would have used dbContext.Projects.Include(p=>p.Clients) and it would give me the project with the client but not the projects of the client because if I wanted that I would have specificed .ThenInclude(c=>c.Projects), but I havent been doing that.

But leave it with me for now as I'm trying to reproduce it in a simple standalone project which I can then share with you. At the moment I'm struggling to get migrations working (Failed to initialize CoreCLR) but once I've got that fixed I'll try reproduce.

@rowanmiller I don't think his problem is with EF but with MVC 6.
MVC 6 now throws exception when you pass model with loop reference.
I'm afraid it will cause tons of confusion. 馃槦

So typically I would have used dbContext.Projects.Include(p=>p.Clients) and it would give me the project with the client but not the projects of the client because if I wanted that I would have specificed .ThenInclude(c=>c.Projects) , but I havent been doing that.

EF shouldn't populate each client with all the projects it has... but it should populate the collection with the ones that are being loaded by your query.

I'm going to close this one out, since the issue with the serialization loop is an MVC thing and you have https://github.com/aspnet/Mvc/issues/4160 open on that front.

Feel free to open a new issue (or re-open this one) if you have a repro that shows EF doing the wrong thing with Include.

Was this page helpful?
0 / 5 - 0 ratings