-2

Consider a database with Order and OrderLines tables and one-to-many relationship between them (this is for MCVE; the actual context is more complex). If I scaffold the model, I get the following:

public partial class Order {
    public virtual ICollection<OrderLines> OrderLines {get; set;}
}

and

public partial class OrderLines {
    public virtual int OrderId {get; set;}
    public virtual Order Order {get; set;}
}

Now, if I generate OrdersController, the GET method is also quite straightforward:

[HttpGet]
public ActionResult<IEnumerable<Order>> Order() {
    return _context.Order.ToList();
}

And I get a nice JSON string in return. However, if I add Include() to the get method like this:

    return _context.Order.Include(o => o.OrderLines).ToList();

the resulting string is cut in the middle. When I debug, it seems that the program gets into infinite loop from OrderLines to Order and then back to OrderLines. If I remove Order variable from OrderLines and only leave OrderId, everything works fine (which supports my hypothesis about infinite loop).

Obviously, it is somewhat primitive example; I should be using ViewModel - but still, shouldn't the code above be valid? I haven't used Include() for years, but I am pretty sure that in earlier versions of EF it was working fine.

What is the recommended way to get the object and its child collection?

6
  • Never return Entity Framework queries, always materialize first Commented Nov 24, 2018 at 19:04
  • sorry - I missed ToList() during cut and paste. Updated Commented Nov 24, 2018 at 19:12
  • 1
    @CamiloTerevinto - I was googling using all kind of keywords, and the question that you referenced never came up. Also, for some reason I didn't get any error. So, while I agree that that question provides correct answer, I would suggest to keep my question open... :) Commented Nov 24, 2018 at 19:21
  • 1
    regarding the duplicate question, the answer is present in several other questions, however, the question is from a different perspective. Many are stuck at this stage and I don't see people with this issue having finding that solution Commented Nov 24, 2018 at 19:22
  • 1
    True the problem is the same. The above question is the common scenario where you face the problem. The scenario cannot really be linked to the problem. It took me a while the first time too. Makes sense to have a question in this format so as to help others find its solution sooner Commented Nov 24, 2018 at 19:34

1 Answer 1

1

Your output object has a circular reference that doesn't get serialized by default.

In your startup class, find the line services.AddMvc() and update it as follows:

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

Check this link for more information.

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

3 Comments

Ouch! I was reading that page but just through Eager and Explicit loading (and Explicit Loading actually works as well); but ignored Lazy loading since it didn't apply to me... Thank you
I would not ask you to use lazy loading. I don't think that applies to real-world application. It's just a shortcut. I provided the link since it contains the same code at the bottom of the page
Understood... I am saying that I stopped at lazy loading and missed the explanation below it. The good thing is that I got a perfect answer that eluded me for a day; although it cost me two downvotes... Oh well

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.