Customised IdentityUserRole primary key

2019-02-22 16:42发布

问题:

I'm using ASP.NET Identity Provider and EF 6 Code First and I have created a custom IdentityUserRole table which has an extra column OrganisationId. The custom table is named UserRole.

The table currently has the default primary key of UserId and RoleId.

I would like to have the OrganisationId column included in the Primary Key of the IdentityUserRole table.

I can see the UserRole table in my database, and it's the one that's being used for the userroles (there's no aspnet_userrole table and the table has data when I assign a role to a user)

I tried this:

modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole").HasKey(x => new { x.UserId, x.RoleId }); 

But it doesn't show me the OrganisationId property.

So I tried:

modelBuilder.Entity<UserRole>().HasKey(x => new { x.OrganisationId, x.RoleId, x.UserId });

But when I add a migration, both the Up and Down methods are empty.

Update (some code)

The IdentityUserRole class:

public class UserRole : IdentityUserRole, IOrganisationEntity
{
    [Key]
    public int OrganisationId { get; set; }

    [ForeignKey("OrganisationId")]
    public Organisation Organisation { get; set; }
}

DbContext inherits from IdentityDbContext<User>

And User inherits from IdentityRebootUser

Update 2

This is the new DbContext:

public class MyDbContext : IdentityDbContext<User, Role, string, 
                             IdentityUserLogin, UserRole, IdentityUserClaim>

and this is my new User class:

public class User : IdentityRebootUser<string, IdentityUserLogin, 
                        Role, IdentityUserClaim>

And the Role class:

public class Role : IdentityRole<string, UserRole>

However, this gives me the following error:

The type 'MyNamespace.Model.Entities.User' cannot be used as type parameter 'TUser' in the generic type or method 'Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>'. There is no implicit reference conversion from 'MyNamespace.Model.Entities.User' to 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser<string, Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin, MyNamespace.Model.Entities.UserRole, Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim>'

Update 3

I got rid of IdentityReboot. I created my own User object which has the following signature:

public class User : IdentityUser<string, IdentityUserLogin, 
                        UserRole, IdentityUserClaim>

I can now modify the UserRole table to add an extra PK, which is what I wanted.

The problem I have now is, that I cannot use the default UserStore, because when I tell it to use my custom 'User' table, I get the following error:

There is no implicit reference conversion from 'MyDB.Model.Entities.User' to 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser'.

So I implemented my own version of IUserStore, which is generating the async errors.

If only there was a way to use UserStore with my custom User object, I would be more than happy.

回答1:

You need to customise all of your identity objects to specify different keys. There are various tutorials online but the best I've found is from www.asp.net.

Essentially you need to make your own version of each object but inherit from the more complex versions. For example, instead of:

public class ApplicationUser : IdentityUser
{
    ...
}

You would do this:

public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, 
CustomUserClaim> 
{ 
    ...
}

And repeat for all object including UserStore, UserManager, RoleManager etc.