IdentityDbContext是一个令人困惑的概念,在Stack Overflow(SO)上搜索会发现很多涉及该主题的问题。
ASP.NET Identity DbContext confusion
How can I change the table names when using Visual Studio 2013 AspNet Identity?
Merge MyDbContext with IdentityDbContext
为了解决这些问题,我们首先需要理解IdentityDbContext的工作原理。需要明确的一点是,IdentityDbContext只是从DbContext继承的一个类,而不是黑匣子!
让我们来看看IdentityDbContext源代码:
public abstract class IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : DbContext
where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin>
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
where TKey : IEquatable<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TRoleClaim : IdentityRoleClaim<TKey>
where TUserToken : IdentityUserToken<TKey>
{
public IdentityDbContext(DbContextOptions options) : base(options)
{ }
protected IdentityDbContext()
{ }
public DbSet<TUser> Users { get; set; }
public DbSet<TUserClaim> UserClaims { get; set; }
public DbSet<TUserLogin> UserLogins { get; set; }
public DbSet<TUserRole> UserRoles { get; set; }
public DbSet<TUserToken> UserTokens { get; set; }
public DbSet<TRole> Roles { get; set; }
public DbSet<TRoleClaim> RoleClaims { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<TUser>(b =>
{
b.HasKey(u => u.Id);
b.HasIndex(u => u.NormalizedUserName).HasName("UserNameIndex").IsUnique();
b.HasIndex(u => u.NormalizedEmail).HasName("EmailIndex");
b.ToTable("AspNetUsers");
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
b.Property(u => u.UserName).HasMaxLength(256);
b.Property(u => u.NormalizedUserName).HasMaxLength(256);
b.Property(u => u.Email).HasMaxLength(256);
b.Property(u => u.NormalizedEmail).HasMaxLength(256);
b.HasMany(u => u.Claims).WithOne().HasForeignKey(uc => uc.UserId).IsRequired();
b.HasMany(u => u.Logins).WithOne().HasForeignKey(ul => ul.UserId).IsRequired();
b.HasMany(u => u.Roles).WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
});
builder.Entity<TRole>(b =>
{
b.HasKey(r => r.Id);
b.HasIndex(r => r.NormalizedName).HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();
b.Property(u => u.Name).HasMaxLength(256);
b.Property(u => u.NormalizedName).HasMaxLength(256);
b.HasMany(r => r.Users).WithOne().HasForeignKey(ur => ur.RoleId).IsRequired();
b.HasMany(r => r.Claims).WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
});
builder.Entity<TUserClaim>(b =>
{
b.HasKey(uc => uc.Id);
b.ToTable("AspNetUserClaims");
});
builder.Entity<TRoleClaim>(b =>
{
b.HasKey(rc => rc.Id);
b.ToTable("AspNetRoleClaims");
});
builder.Entity<TUserRole>(b =>
{
b.HasKey(r => new { r.UserId, r.RoleId });
b.ToTable("AspNetUserRoles");
});
builder.Entity<TUserLogin>(b =>
{
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
b.ToTable("AspNetUserLogins");
});
builder.Entity<TUserToken>(b =>
{
b.HasKey(l => new { l.UserId, l.LoginProvider, l.Name });
b.ToTable("AspNetUserTokens");
});
}
}
基于源代码,你所需做的就是创建一个继承自IdentityDbContext且具有访问这些类的DbContext。
public class ApplicationDbContext
: IdentityDbContext
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
static ApplicationDbContext()
{
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
如果您想进一步扩展类,请查看
AspNet Identity 2.0可扩展项目模板。
IdentityRole
强制转换为ApplicationRole
。我刚刚尝试将IdentityUserRole
转换为ApplicationUserRole
,我的自定义属性是可访问的。虽然如果你正在定制超出ApplicationUser
的类,你可能需要等待 ASP.NET Identity 2.0。它有一个新的IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>
基类,可以让你指定所有自定义实体。 - Anthony Chupublic class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationLogin, ApplicationUserRole, ApplicationClaim>
(int
(或string
)是用户主键的类型)。 - Anthony Chu