Peter Morris
Peter Morris

Reputation: 23234

How can I load an object graph in Entity Framework Core?

I have some relational data that I need to fetch

from user in Users
  .Include("UserCategoryPermissions")
  .Include("UserResourcePermissions")
  .Include("UserPermissions.Permission.Application")
  .Include("UserGroupMembers.UserGroup.UserGroupPermissions.Permission.Application")
where user.Id == 3

Entity Framework Core is fetching this data by executing multiple queries. All I want to do is load an object graph into memory (no projection), and multiple-queries are going to really slow things down.

I can pre-load these objects by doing a massive query with lots of joins

from a in A
join b in B on a.Id equals b.A_Id into bJoin from b in bJoin.DefaultIfEmpty()
join c in C on b.Id equals c.B_Id into cJoin from c in cJoin.DefaultIfEmpty()
join x in X on a.Id equals x.A_Id into xJoin from x in xJoin.DefaultIfEmpty()
// etc
select new {
  a, b, c, x
}

But having to do this every time I want to fetch data would be a real pain. Is there a way I can get Entity Framework Core to pre-load a graph of data? Ideally, I want it to work from an array of strings, where each string identifies a path (as I have above), but I'll be happy to learn of any way these graphs could be passed via a parameter to a method.

Upvotes: 1

Views: 1261

Answers (1)

Oliver
Oliver

Reputation: 45101

I'd normally use the lambda syntax and it fetches all data in one call:

using System.Linq;
using Microsoft.EntityFrameworkCore;
...

var userFound = context.Users
    .Include(user => user.UserCategoryPermissions)
    .Include(user => user.UserResourcePermissions)
    .Include(user => user.UserPermissions)
    .ThenInclude(map => map.Permission)
    .ThenInclude(permission => permission.Application)
    .Include(user => user.UserGroupMembers)
    .ThenInclude(members => members.UserGroup)
    .ThenInclude(group => group.UserGroupPermissions)
    .ThenInclude(map => map.Permissions)
    .ThenInclude(permission => permission.Application)
    .Where(user => user.Id == 3);

Be aware that within the lambda of the Include and ThenInclude intellisense not works properly. Simply blind type the correct property name and it works.

Upvotes: 1

Related Questions