【问题标题】:Add custom column in AspNetRoles results in Invalid Column Name Discriminator在 AspNetRoles 中添加自定义列导致 Invalid Column Name Discriminator
【发布时间】:2017-02-03 22:59:39
【问题描述】:

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

我正在尝试自定义 AspNetRoles,方法是添加一个名为 MyCustomColumn

的列

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

列名鉴别器无效

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

如何处理?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-5 asp.net-identity-2 asp.net-roles discriminator


    【解决方案1】:

    实际上,这些都不是必需的。很可能您未能更新上下文以从IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> 继承,而不是默认的IdentityDbContext<TUser>。由于您没有将自定义角色实体作为 TRole 类型参数传递,因此上下文使用 IdentityRole 作为类类型。然后它为IdentityRole 创建一个表,看到您的自定义角色继承自IdentityRole,因此添加了鉴别器列,以便它可以区分数据库中IdentityRole 的实例和您的自定义角色之间的区别(单表继承是 EF 采用的默认策略)。

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

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

    不要

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    

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

    【讨论】:

    • 感谢您的贡献,但非常感谢您提供代码示例(我对 Identity 很陌生)。还有,这个项目是 DB-first,所以即使 Code-first 很有趣,我也不能在这里使用。
    • 是的,你可以。这就是我的观点。尽管名称如此,但代码优先可以与现有数据库一起使用。数据库优先和模型优先 (EDMX) 已被弃用,取而代之的是 Code first。
    • 另外,示例代码非常不言自明,但我更新了我的答案以更明确地拼写出来。
    【解决方案2】:

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

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

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

    在模型文件夹中

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


    然后,让我们创建一个继承自RoleManager&lt;ApplicationRole&gt; 的类。 我把它放在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 类。

    现在我们必须在启动时注册我们的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();
    

    【讨论】:

    • 这很有用,但是为什么我们需要在 AspNetRoles 表中添加 Discriminator 字段呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 2019-11-20
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    相关资源
    最近更新 更多