1

I tried searching but couldn't find an exact answer to this on docs.microsoft at: https://learn.microsoft.com/en-us/ef/core/querying/related-data#eager-loading

I have this bit of code:

await MyDbContext.Users.Where(u => u.Id == Id).Include(u => u.UserContacts).ThenInclude(uC => uC.Contact);

The return type is of type User and Contact is also of type User.

When I debug and step through, it seems like all the Contacts of the required User are loaded, as well as all their Contacts, and then all their Contacts, and so on.

Question:

  1. Is this expected behavior for EF and if so, doesn’t this impact performance, having to look up the DB to such depths?
  2. Is there a way for me to specify a kind of 'max depth'?

The closest match to what I'm asking here that I cam across was probably this SO thread: How does Entity Framework work with recursive hierarchies? Include() seems not to work with it

AjLearning
  • 379
  • 5
  • 16
  • I found this thread: https://stackoverflow.com/questions/53174003/ef-core-creating-object-with-infinite-depth. The answer suggests that it’s simply the debugger letting me ‘glimpse’ at related children. Not sure whether this is all it is or whether the object being returned actually contains these deep references? Still confused. – AjLearning Aug 17 '19 at 12:33
  • You can check what the resulting query is (it appears in the output window). This will just be a join of the Users table with itself. Are you sure you haven't loaded users in the same context in previous queries? If they are already loaded then you will see them even if you didn't ask for them to be loaded. – JerMah Aug 17 '19 at 13:41
  • @JerMah Thanks for that. Yea I get the join of the Users table on itself. Given the Include and relation, I’d expect that. But joins arent to infinite depth though? Also no, definitely haven’t loaded other users previously as I’m debugging the very first query. – AjLearning Aug 17 '19 at 14:33

1 Answers1

1

You can navigate to entities that your eager loading query doesn't specify in two scenarios:

  • Navigation Property Fix-UP

If a query, or a previous query on the same DbContext has loaded an Entity that is the target of a Navigation Property, the change tracker will "fix up" the navigation property.

  • Lazy Loading

Obviously if Lazy Loading is enabled, Navigation Properties will be loaded as you access them.

David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
  • Thanks David. Pretty sure lazy loading is not enabled in this application, as my navigation properties are null if I don’t explicitly include them. Does Fix-UP affect the debugger? Because when I expand to see details of a navigation property, it does not appear straight away but rather seems as though the debugger is taking time to ‘evaluate’ it. – AjLearning Aug 17 '19 at 16:22
  • That sounds like Lazy Loading. If you have IntelliTrace you can see the query events while debugging. https://learn.microsoft.com/en-us/visualstudio/debugger/intellitrace?view=vs-2019 – David Browne - Microsoft Aug 17 '19 at 16:25
  • If it is indeed lazy loading, I should be able to not explicitly `Include` in my example, and instead do something like this: `var contacts = user?.UserContacts.ToList()`. Correct? However that does not work. If I try doing that I get a Null exception. The debugger also does not like me inspecting `UserContacts` for a `User` object that I've queried without specifying `Include`. – AjLearning Aug 17 '19 at 16:47
  • @David-Browne-Microsoft Ok so as it turns out, the `Contact`s that I did not explicitly ask for were probably fixed-up as a result of another `Include` I had further down the list of includes, which possibly loaded these entities, making it seem like it was going down to an unlimited depth. – AjLearning Aug 17 '19 at 17:04