Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Circular References #4646

Closed
capesean opened this issue Feb 26, 2016 · 7 comments
Closed

Circular References #4646

capesean opened this issue Feb 26, 2016 · 7 comments

Comments

@capesean
Copy link

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:
aspnet/Mvc#4160

@gdoron
Copy link

gdoron commented Feb 26, 2016

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.

@OlegKi
Copy link

OlegKi commented Feb 26, 2016

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?

@gdoron
Copy link

gdoron commented Feb 26, 2016

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

@rowanmiller
Copy link
Contributor

@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?

@capesean
Copy link
Author

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.

@gdoron
Copy link

gdoron commented Feb 28, 2016

@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. 😟

@rowanmiller
Copy link
Contributor

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 aspnet/Mvc#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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants