我是EF6代码优先方法的新手。所以请原谅
我正在尝试为我的本地项目实现AspNetIdentity框架。
我有数据库中所有开箱即用的表。我对模型类结构保持原样。我没有角色,只有一个角色。
这是我的DbContext类。
public class AuthDbContext : IdentityDbContext<IdentityUser>
{
public AuthDbContext()
: base("AuthDbContext")
{
Database.SetInitializer<AuthDbContext>(null);
}
public virtual DbSet<AspNetRole> AspNetRoles { get; set; }
public virtual DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual DbSet<AspNetUser> AspNetUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(t => t.UserId);
modelBuilder.Entity<IdentityRole>().HasKey<string>(t => t.Id);
modelBuilder.Entity<IdentityUser>().HasKey<string>(t => t.Id);
modelBuilder.Entity<IdentityUserRole>().HasKey(t => new { t.RoleId,t.UserId});
modelBuilder.Ignore<IdentityUserRole>();
modelBuilder.Ignore<AspNetRole>();
}
表中有2个用户。我正在努力找一个。我收到错误无效列名"鉴别器"我在生成模型时做错了什么?我尝试了很多选项,但我无法解决这个
以下是为userManager.FindByName方法生成的sql
exec sp_executesql N'SELECT
[Limit1].[C1] AS [C1],
[Limit1].[Id] AS [Id],
[Limit1].[Email] AS [Email],
[Limit1].[EmailConfirmed] AS [EmailConfirmed],
[Limit1].[PasswordHash] AS [PasswordHash],
[Limit1].[SecurityStamp] AS [SecurityStamp],
[Limit1].[PhoneNumber] AS [PhoneNumber],
[Limit1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Limit1].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Limit1].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Limit1].[LockoutEnabled] AS [LockoutEnabled],
[Limit1].[AccessFailedCount] AS [AccessFailedCount],
[Limit1].[UserName] AS [UserName]
FROM ( SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Email] AS [Email],
[Extent1].[EmailConfirmed] AS [EmailConfirmed],
[Extent1].[PasswordHash] AS [PasswordHash],
[Extent1].[SecurityStamp] AS [SecurityStamp],
[Extent1].[PhoneNumber] AS [PhoneNumber],
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed],
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled],
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc],
[Extent1].[LockoutEnabled] AS [LockoutEnabled],
[Extent1].[AccessFailedCount] AS [AccessFailedCount],
[Extent1].[UserName] AS [UserName],
''0X0X'' AS [C1]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE ([Extent1].[Discriminator] = N''User'') //Error here ?????????
AND (((UPPER([Extent1].[UserName])) = (UPPER(@p__linq__0))) OR ((UPPER([Extent1].[UserName]) IS NULL) AND (UPPER(@p__linq__0) IS NULL)))
) AS [Limit1]',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'testUser'
正如您在Asp.NET Identity 2.0的源代码中看到的,IdentityDbContext<T>
已经在OnModelCreating
中定义DbModelBuilder
配置CCD_ 4,CCD_ 5,CCD_ 6,DbSet<AspNetUser>
,所以您不必定义所有这些属性,也不必覆盖OnModelCreating
。
你的上下文应该是这样的:
public class AuthDbContext : IdentityDbContext<IdentityUser>
{
public AuthDbContext() : base("AuthDbContext")
{
Database.SetInitializer<AuthDbContext>(null);
}
}
您正在定义一个DbSet<AspNetUser>
,并且您的Context继承自Identity<IdentityUser>
,因此有两个DbSets
,其中一个是T
是IdentityUser
,另一个是其中T
是AspNetUser
。IdentityUser
继承自AspNetUser
,因此EntityFramework
通过添加一个名为Discriminator的列来管理继承。
编辑:
这是您从中继承的类的实现。
/// <summary>
/// DbContext which uses a custom user entity with a string primary key
/// </summary>
/// <typeparam name="TUser"></typeparam>
public class IdentityDbContext<TUser>
: IdentityDbContext<
TUser,
IdentityRole,
string,
IdentityUserLogin,
IdentityUserRole,
IdentityUserClaim>
where TUser : IdentityUser
{
/// <summary>
/// Default constructor which uses the DefaultConnection
/// </summary>
public IdentityDbContext()
: this("DefaultConnection")
{ }
/// <summary>
/// Constructor which takes the connection string to use
/// </summary>
/// <param name="nameOrConnectionString"></param>
public IdentityDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{ }
}
正如您所看到的,类IdentityDbContext<TUser>
继承自IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>
。后者已经定义了类型IDbSet<TRole>
和IDbSet<TUser>
的属性,并且已经实现了OnModelCreating
,在我看来它满足了您的需求。
/// <summary>
/// Maps table names, and sets up relationships between the various user entities
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
}
// Needed to ensure subclasses share the same table
var user = modelBuilder.Entity<TUser>().ToTable("AspNetUsers");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName).IsRequired();
// CONSIDER: u.Email is Required if set on options?
// Look into IValidatable...
// Try this (Configure Join table name HasMany.WithMany.Map(To match 1.0 tables)
modelBuilder.Entity<TUserRole>()
.HasKey(r => new { r.UserId, r.RoleId })
.ToTable("AspNetUserRoles");
modelBuilder.Entity<TUserLogin>()
.HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId })
.ToTable("AspNetUserLogins");
modelBuilder.Entity<TUserClaim>()
.ToTable("AspNetUserClaims");
var role = modelBuilder.Entity<TRole>().ToTable("AspNetRoles");
role.Property(r => r.Name).IsRequired();
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);
}
如果您想使用自己的AspNetRole
、AspNetUserClaim
和AspNetUserLogin
,您应该从IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>
继承并传递自定义实体,或者如果您想真正控制数据库,您应该简单地从DbContext
继承并自己完成所有设置(您已经在做的事情)。
我希望我说得很清楚,如果你有任何疑问,请毫不犹豫地发表评论。