Explicit Loading nested related models in Entity Framework

asp.net-mvc-5 c# entity-framework-6

Question

I'm working on an ASP.NET MVC5 project using EF6. I have 3 models: user, role and permission.

The relation between user and role is many to many. The relation between role and permission is many to many.

LazyLoadingEnabled is disabled in the database context.

public class Permission
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}

public class Role
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Permission> Permissions { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

public class User
{
    public int ID { get; set; }
    public string Username { get; set; }
    public string DisplayName { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
}

public class TaskManagerDB : DbContext
{
    public TaskManagerDB() : base()
    {
        Configuration.LazyLoadingEnabled = false;
    }

    public DbSet<Role> Roles { get; set; }
    public DbSet<Permission> Permissions { get; set; }
    public DbSet<User> Users { get; set; }
}

At an earlier point, I fetch a given user:

User user = db.Users.Find(1);

Now: since I already have the model, how can I load the user roles with their permissions?

I have tried:

db.Entry(user).Collection(x => x.Roles).Query().Include(y => y.Permissions).Load();

But it's not working - user.Roles is still null.

The following solution is not acceptable because I already have the user Model:

User user = db.Users.Include("Roles.Permissions").Where(x => x.ID == 1).FirstOrDefault();
1
3
4/22/2018 4:41:57 PM

Accepted Answer

What you have tried

db.Entry(user).Collection(x => x.Roles).Query()
    .Include(y => y.Permissions)
    .Load();

is indeed the intended way. And it works for everything else except the many-to-many relationship with implicit junction table, which is the case here.

I don't know if it's a bug or "by design", but the solution is to Include the other (calling) end of the relationship, e.g.

db.Entry(user).Collection(x => x.Roles).Query()
    .Include(y => y.Users) // <--
    .Include(y => y.Permissions)
    .Load();
8
4/22/2018 5:33:20 PM

Popular Answer

One way of getting the roles and permissions for a user:

db.Roles.Include("Permissions").Where(r => r.Users.Select(u => u.ID).Contains(user.ID));


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow