1

Considering a table [Person] which has two foreign keys ([Phone_Numbers], [Business_Information]). When using EF Core, we can simply find a Person using the dbContext.Find method like var person = await db.Context.FindAsync<Person>(1); however, the Find method only looks for the entity inside the tracking cache and it does not handle relational properties. In order to solve this, we can call the Entry method to attach those properties like dbContext.Entry<Person>(person).Reference(x=> x.Business_Information). Considering the provided example, we have to call the Entry method twice in this case:

dbContext.Entry<Person>(person).Reference(x=> x.Business_Information).Load();
dbContext.Entry<Person>(person).Collection(x=> x.Phone_Numbers).Load();

An alternative solution is to use the Include method:

var person = await dbContext.Set<Person>().Include("Business_Information").Include("Phone_Numbers").FirstOrDefaultAsync(x=> x.id == id);

The first solution sends two request to the Db (I think the Find method does not send a request if the entity is being tracked); however, I'm not sure how the second one works and accordingly I'm also unsure if it has any performance advantages. I've been thinking the first solution could be faster and more efficient. I'd appreciate if someone clarifies this for me.

Arnold Zahrneinder
  • 4,788
  • 10
  • 40
  • 76

1 Answers1

3

It really depends on number of related properties, their type (reference or collection) and in the first case - if they are already loaded or not.

Let say your entity has N reference navigation properties and M collection navigation properties that you want to load.

The approach with Include will always execute 1 + M db queries - one for the entity + reference properties which data is retrieved with JOINs to the corresponding tables and returned as columns in the query result) and one for each collection - regardless of whether the entity and any of the related entities/collections is already loaded.

The approach with explicit loading is more dynamic.

It will execute 1 db query for the entity if it's not loaded in the context, 0 otherwise.

For each reference navigation property it will execute 1 db query if the referenced entity is not already loaded in the context, 0 otherwise.

For each collection navigation property, it will execute 1 db query if the collection is not marked as loaded (db.Entry(entity).Collection(e => e.Collection).IsLoaded == false), 0 otherwise.

At the end, the explicit loading approach could execute between 0 and 1 + N + M db queries.

With all that being said, it's not clear which one is better. If you are using relatively short lived DbContext instances, hence the chances of not execution related queries is low, I would go with Include approach because it is deterministic.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343