我正在使用带有 Identity 2 框架的ASP.NET MVC5,数据库优先
我正在尝试通过添加名为 MyCustomColumn
的列来自定义AspNetRoles
然而,我的应用程序崩溃是因为:
无效的列名称识别器
网上有很多SO和其他网站的资源,但大多数都使用CodeFirst方法,我不能在我的应用中使用它们。
如何处理?
答案 0 :(得分:5)
实际上,这都不是必需的。很可能您无法更新您的上下文以继承IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>
,而不是默认的IdentityDbContext<TUser>
。由于您未将自定义角色实体作为TRole
类型参数传递,因此上下文使用IdentityRole
作为类类型。然后它为IdentityRole
创建一个表,看到您的自定义角色继承自IdentityRole
,因此添加了Discriminator列,以便它可以告诉IdentityRole
的实例和您的自定义之间的不同角色,在数据库中(单表继承是EF使用的默认策略)。
这将技术上工作,但您的自定义角色将永远不会被使用。使用正确的通用抽象上下文类,你会没事的。
对于它的价值,你也应该取消EDMX的东西。它已被弃用,错误和不必要。尽管名称如此,“Code First”可以与现有数据库一起使用,也可以创建一个新数据库。
<强>不强>
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
<强> DO 强>
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
答案 1 :(得分: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<ApplicationRole>
的类。
我将它放在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();