我是EF6的Code first Approach的新手。请原谅
我正在尝试为我的本地项目实施AspNetIdentityframework。
我拥有数据库中开箱即用的所有表。我保持与模型类结构相同。我没有角色只有1个角色。
这是我的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个用户。我想找一个。 我收到错误列名无效&#39;判别器&#39; 在生成模型时我做错了什么? 我尝试了很多我无法解决的选项
这是为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'
答案 0 :(得分:2)
正如您在Asp.NET Identity 2.0的源代码中看到的那样here,IdentityDbContext<T>
已经存在
定义DbModelBuilder
中的OnModelCreating
配置和。{1}}
DbSet<AspNetRole>
,
DbSet<AspNetUserClaim>
,
DbSet<AspNetUserLogin>
,
DbSet<AspNetUser>
,因此您不必定义所有这些属性,也不必覆盖OnModelCreating
。
你的上下文应该是这样的:
public class AuthDbContext : IdentityDbContext<IdentityUser>
{
public AuthDbContext() : base("AuthDbContext")
{
Database.SetInitializer<AuthDbContext>(null);
}
}
您正在定义DbSet<AspNetUser>
,并且您的上下文继承自Identity<IdentityUser>
,因此有2 DbSets
,其中T
为IdentityUser
,另一个T
1}}是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
并自己做所有的设置(你已经在做的事情)。
我希望我很清楚,如果您有任何疑问,请发表评论毫不犹豫。