0

I extended the IdentityDBContext to rename the table names, but it looks like i lost the many to many relationship between the users and roles. The LINQ is not picking up the right relationship anymore (p.s. see the intellisence screenshot):

namespace Carbon.Models {
    public partial class CarbonEDM :  IdentityDbContext<User, Role, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>{
        public CarbonEDM()
            : base("name=CarbonDB") {
        }

        public DbSet<Message> Messages { get; set; }


        public static CarbonEDM Create() {
            return new CarbonEDM();
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {

            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<User>().ToTable("Users", "dbo");
            modelBuilder.Entity<Role>().ToTable("Roles", "dbo");
            modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles", "dbo") ;
            modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims", "dbo");
            modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins", "dbo");

        }
    }
}

enter image description here

Update 1

As the answers suggested, there is no navigational properties on Identity roles model, so i tried the following:

    var users = from usr in db.Users
                select new UserInfoViewModel{
                    email = usr.Email,
                    name = usr.Name,
                    role_name = db.Roles.Find(usr.Roles.FirstOrDefault().RoleId).Name
                };

But still im gettin another error: Method 'Carbon.Models.Role Find(System.Object[])' declared on type 'System.Data.Entity.IDbSet1[Carbon.Models.Role]' cannot be called with instance of type 'System.Data.Entity.Core.Objects.ObjectQuery1[Carbon.Models.Role]

I just want to get a list of all the users and their role.

Yehia A.Salam
  • 1,987
  • 7
  • 44
  • 93
  • What does a `UserInfoViewModel` look like? That's the type of the generic argumnet of `users` (you can also hover your mouse over the var in VS to have the compiler remind you of the type). – ryanyuyu Jan 23 '15 at 23:08

2 Answers2

1

User.Roles is not a collection of Role objects. Users to Roles is a many-to-many relationship, so between Users and Roles there is IdentityUserRoles table that has only 2 columns: UserId and RoleId - and this is exactly what you are picking up. This is not because you have renamed the tables - this is by default.

To get role objects for user - get all RoleId for this user, then get all roles with provided IDs.

trailmax
  • 34,305
  • 22
  • 140
  • 234
  • yea but shouldn't linq detect automatically the many to many relationship with the intermediate table, something like this http://www.entityframeworktutorial.net/EntityFramework4.3/add-many-to-many-entity-using-dbcontext.aspx, and provide a collection for User.Roles instead of the intermediate table – Yehia A.Salam Jan 24 '15 at 00:51
  • Identity does not provide these navigation properties. That is just how it is coded. I believe this is done so Identity can be used with many different persistence technologies, not just EF. – trailmax Jan 24 '15 at 01:06
  • @trailnax i updated the question, still cant get the list of users with roles with a normal ef query – Yehia A.Salam Jan 24 '15 at 12:31
  • 1
    Also for background, there are some pretty serious perf implications when we had navigation properties in both directions, as not only were all the users's roles loaded, but also all of the users in each role were also loaded. In 2.2/3.0 we've moved away from using navigation properties and directly querying for performance reasons – Hao Kung Feb 01 '15 at 21:31
0

In your user model you can specify a collection of roles and in your role model you can specify a collection of users. This should create navigation properties.

for example:

public class User{

ICollection<Role> Roles {get; set;}

}

And

public class Role{

ICollection<User> Users {get; set;}

}

Then you can use explicit or eager loading to load the roles as needed.