AddToRole 和 IdentityRole 不是当前上下文模型的一部分

AddToRole and IdentityRole is not part of the model for the current context

我正在使用 Identity 2.1 来处理我的 asp.net 应用程序中的用户角色。到目前为止一切顺利,我创建了从 IdentityDBContext 扩展的新上下文,扩展了 IdentityUser 和 IdentityRole 以添加几个新字段。但是,每当我尝试使用 UserManager 将用户添加到特定角色时,我都会收到 The entity type IdentityRole is not part of the model for the current context.。所以用户角色关系似乎有问题,这是我目前的代码供参考:

用户

public class User : IdentityUser{

    public string Name { get; set; }
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager, string authenticationType) {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
        // Add custom user claims here
        return userIdentity;
    }
}

角色

public partial class Role : IdentityRole
{
    public string Description { get; set; }
}

数据库上下文

namespace Carbon.Models {

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

        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");
        }
    }
}

ApplicationUserManager

public class ApplicationUserManager : UserManager<User>
{
    public ApplicationUserManager(IUserStore<User> store)
        : base(store)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {

        var manager = new ApplicationUserManager(new UserStore<User>(context.Get<CarbonEDM>()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<User>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = false,
            RequireDigit = false,
            RequireLowercase = false,
            RequireUppercase = false,
        };

        // Configure user lockout defaults
        manager.UserLockoutEnabledByDefault = true;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        manager.MaxFailedAccessAttemptsBeforeLockout = 5;

        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = 
                new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }
}

最后,每当我在迁移中播种时都会出现错误:

    protected override void Seed(Carbon.Models.CarbonEDM context)
    {

        DbContextTransaction transaction = null;
        transaction = context.Database.BeginTransaction();

        if (!context.Roles.Any()) {
            var roleStore = new RoleStore<Role>(context);
            var roleManager = new RoleManager<Role>(roleStore);

            roleManager.Create(new Role { Name = "Admin" });
            roleManager.Create(new Role { Name = "Control Unit Operator" });
            roleManager.Create(new Role { Name = "Lab Operator" });
            roleManager.Create(new Role { Name = "Production Engineer" });
            roleManager.Create(new Role { Name = "Production Operator" });
        }

        if (!context.Users.Any()) {
            var userStore = new UserStore<User>(context);
            var userManager = new ApplicationUserManager(userStore);

            var _user = new User {
                Email = "yehiasalam@live.com",
                PhoneNumber = "+20 12 23461340",
                Name = "Yehia A.Salam",
                UserName = "yehiasalam@live.com"
            };
            userManager.Create(_user, "pass@word");
            userManager.AddToRole(_user.Id, "Admin"); /* IdentityRole error here */

        }

        context.SaveChanges();
        transaction.Commit();


        base.Seed(context);
    }
}

抱歉这么长post,我试着把所有的都包括进去。

好的,所以问题出在 UserStore,默认声明是

public class UserStore<TUser> : UserStore<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUserStore<TUser>, IUserStore<TUser, string>, IDisposable where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser {

它显式声明了 IdentityRole,而不是使用像 TUser 这样的通用符号,所以我们只需要创建另一个 class 从父 UserStore 扩展:

public class CarbonUserStore<TUser> : UserStore<TUser, Role, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUserStore<TUser>, IUserStore<TUser, string>, IDisposable where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser {

    public CarbonUserStore(DbContext context) :base(context) {}     }

微软不酷,我花了一天时间想办法等等。但是,它被添加到随 vNext 一起提供的 Identity 包中(必须喜欢它的开源): https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs

public class UserStore<TUser, TRole, TContext> : UserStore<TUser, TRole, TContext, string>
    where TUser : IdentityUser, new()
    where TRole : IdentityRole, new()
    where TContext : DbContext
{
    public UserStore(TContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
}