AspNetIdentity框架代码第一种方法

时间:2015-04-15 18:43:57

标签: entity-framework-6 asp.net-identity code-first

我是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'

1 个答案:

答案 0 :(得分:2)

正如您在Asp.NET Identity 2.0的源代码中看到的那样hereIdentityDbContext<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,其中TIdentityUser,另一个T 1}}是AspNetUserIdentityUser继承自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);
}

如果您想使用自己的AspNetRoleAspNetUserClaimAspNetUserLogin,则应继承IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim>并传递自定义实体,或者如果您想要你可以控制你的数据库,只需继承DbContext并自己做所有的设置(你已经在做的事情)。

我希望我很清楚,如果您有任何疑问,请发表评论毫不犹豫。