在 AspNetRoles 中添加自定义列会导致无效的列名鉴别器

Add custom column in AspNetRoles results in Invalid Column Name Discriminator

我正在使用 ASP.NET MVC5 和 Identity 2 框架,数据库优先

我正在尝试通过添加名为 MyCustomColumn

的列来自定义 AspNetRoles

但是,我的应用程序崩溃了,因为:

Invalid Column Name Discriminator

SO 和网络上的其他地方有很多资源,但大多数都是使用 CodeFirst 方法,我无法在我的应用程序中使用它们。

如何处理?

好的,因为我花了几个小时来寻找解决方案,所以我 post 在这里,如果它可以帮助其他人的话。

首先,在 AspNetRoles 中创建您的自定义列 AND 一个名为 Discriminator 的列(这是一个 nvarchar(max) )。更新您的 .edmx

然后,我们必须创建一个继承自IdentityRole的class。我们将使用此 class 访问我们刚刚创建的自定义列:

在模型文件夹中

public ApplicationRole()
        : base() { }

    public ApplicationRole(string name, long myCustomValue)
        : base(name)
    {
        MyCustomValue = myCustomValue;
    }

    public virtual long MyCustomValue { get; set; }


然后,让我们创建一个继承自 RoleManager<ApplicationRole> 的 class。 我将它放在 IdentityConfig.cs 中,但最好将它放在其他位置...
有关信息,我从 this blog 重新实现 RoleStore 和 ApplicationRoleManager 段落

中得到启发
public class ApplicationRoleManager : RoleManager<ApplicationRole>
{
    public ApplicationRoleManager(
        IRoleStore<ApplicationRole, string> roleStore)
        : base(roleStore)
    {
    }
    public static ApplicationRoleManager Create(
        IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
    {
        return new ApplicationRoleManager(
            new RoleStore<ApplicationRole>(context.Get<ApplicationDbContext>()));
    }
}

ApplicationRoleManager 有一个构造函数调用我们之前创建的 ApplicationRole class.

现在我们必须在启动时注册我们的ApplicationRoleManager,所以我们必须在其他行之后添加这一行CreatePerOwinContext

在App_Start\Startup.auth.cs中,ConfigureAuth(IAppBuilder app)方法

app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);


所以现在我们可以使用我们的ApplicationRoleManager,正确实例化:

var rm = new ApplicationRoleManager(new RoleStore<ApplicationRole>(new ApplicationDbContext()));

然后我们想怎么用就怎么用

var roleName = rm.FindByName("Admin");
string myCustomData = roleName.CustomData.ToString();

其实,none这个是有必要的。您很可能无法更新您的上下文以继承自 IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>,而不是默认的 IdentityDbContext<TUser>。由于您没有将自定义角色实体作为 TRole 类型参数传递,因此上下文改为使用 IdentityRole 作为 class 类型。然后它为 IdentityRole 创建一个 table,看到您的自定义角色继承自 IdentityRole,因此添加鉴别器列,以便它可以区分 [=15= 的实例之间的差异] 和您的自定义角色,在数据库中(单个 table 继承是 EF 使用的默认策略)。

这在技术上 会起作用,但您的自定义角色永远不会被实际使用。使用正确的通用抽象上下文 class,你会没事的。

为了它的价值,你也应该去掉 EDMX 的东西。它已被弃用,有错误且不必要。尽管名称如此,"Code First" 可用于现有数据库或创建新数据库。

不要

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

DO

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>