为啥 EF Core 2.2 总是更新“AspNetUsers”表中的“ConcurrencyStamp”、“PasswordHash”?

Posted

技术标签:

【中文标题】为啥 EF Core 2.2 总是更新“AspNetUsers”表中的“ConcurrencyStamp”、“PasswordHash”?【英文标题】:Why EF Core 2.2 always updates "ConcurrencyStamp", "PasswordHash" in "AspNetUsers" table?为什么 EF Core 2.2 总是更新“AspNetUsers”表中的“ConcurrencyStamp”、“PasswordHash”? 【发布时间】:2020-01-02 00:17:24 【问题描述】:

我有 .net 核心应用程序,它使用 ef core 2.2 代码优先模型, 当我跑步时

添加迁移

它总是更新"AspNetUsers" 表中的"ConcurrencyStamp", "PasswordHash" 列值。

自动生成的UP方法内容是

        migrationBuilder.UpdateData(
            table: "AspNetUsers",
            keyColumn: "Id",
            keyValue: new Guid("b0bea27d-5eae-4836-8f85-8bf8f1aed8d5"),
            columns: new[]  "ConcurrencyStamp", "PasswordHash" ,
            values: new object[]  "c599b745-8e24-438b-bd62-8264102ac960", "AQAAAAEAACcQAAAAEHjqRSJuPQtzpQR7L7hUNo3vFM8P9dhHkiXQjYRpdgS1Z9I9TXQ2XwhM9CQiE0oVyg==" );

        migrationBuilder.UpdateData(
            table: "AspNetUsers",
            keyColumn: "Id",
            keyValue: new Guid("b0bea27d-5eae-4836-8f85-8bf8f1aed8d6"),
            columns: new[]  "ConcurrencyStamp", "PasswordHash" ,
            values: new object[]  "bdbc0bcf-6eaa-489b-b2a2-9c1742a38bf4", "AQAAAAEAACcQAAAAEBpVzPQl74gxL+V93biLDmn4oKNJSZZ5VDUpwSQ/S8h+itGvGbScqG78Wi35bmN4dQ==" );

我的OnModelCreating方法如下

protected override void OnModelCreating(ModelBuilder modelBuilder)

    base.OnModelCreating(modelBuilder);

    modelBuilder.ApplyConfigurations(
        typeof(SampleDBContext).Assembly,
        typeof(IEntityTypeConfiguration<>));

    DatabaseSeeder.Seed(modelBuilder);

在种子方法中,我调用一个方法来为应用程序用户提供种子。

    private static void SeedApplicationUser(ModelBuilder modelBuilder)
    
        var hasher = new PasswordHasher<ApplicationUser>();

        var admin = new ApplicationUser
        
            Id = Guid.Parse("b0bea27d-5eae-4836-8f85-8bf8f1aed8d4"),
            RoleType = RoleTypes.Admin,
            Email = "admin@gmail.io",
            NormalizedEmail = "ADMIN@GMAIL.IO",
            EmailConfirmed = true,
            UserName = "admin",
            NormalizedUserName = "ADMIN",
        ;

        var user1 = new ApplicationUser
        
            Id = Guid.Parse("b0bea27d-5eae-4836-8f85-8bf8f1aed8d5"),
            RoleType = RoleTypes.User,
            Email = "user1@gmail.io",
            NormalizedEmail = "USER1@GMAIL.IO",
            EmailConfirmed = true,
            UserName = "user1",
            AccessFailedCount = 0,
            NormalizedUserName = "USER1",
        ;

        var user2 = new ApplicationUser
        
            Id = Guid.Parse("b0bea27d-5eae-4836-8f85-8bf8f1aed8d6"),
            RoleType = RoleTypes.User,
            Email = "user2@gmail.io",
            NormalizedEmail = "USER2@GMAIL.IO",
            EmailConfirmed = true,
            UserName = "user2",
            AccessFailedCount = 0,
            NormalizedUserName = "USER2",
        ;

        admin.PasswordHash = hasher.HashPassword(admin, "admin@23");
        user1.PasswordHash = hasher.HashPassword(user1, "user1@23");
        user2.PasswordHash = hasher.HashPassword(user2, "user2@23");

        modelBuilder.Entity<ApplicationUser>()
            .HasData(admin, user1, user2);
    

这是正常行为还是我错过了什么?

如果有人需要更多详细信息,请发表评论。 我不知道要提供什么。

谢谢,

【问题讨论】:

你能分享一下 OnModelCreating 方法吗?如果您可以添加更多相关代码。 请查看我更新的问题 DatabaseSeeder.Seed(modelBuilder) 中有什么内容? 以及所有 IEntityConfiguration 实现中的内容,因为它可能是一个问题。 @GertArnold 查看我更新的问题。我在 seed() 方法中调用一个方法来为应用程序用户播种。 【参考方案1】:

ConcurrencyStamp 总是在创建新对象时生成。

public virtual string ConcurrencyStamp  get; set;  = Guid.NewGuid().ToString();

PasswordHash 也是如此。它的值总是在你的种子中重新生成并且总是different(即使是相同的密码)。

这就是 EF Core 看到数据库中数据和种子数据之间差异的原因。每次创建新迁移时,这两个字段的值都不同。

快速但不是最好的解决方法是始终使用相同的硬编码哈希和并发标记,但这确实是错误的。

使用自定义初始化逻辑会更好,这在这个问题中有很好的描述:How to seed an Admin user in EF Core 2.1.0?

【讨论】:

以上是关于为啥 EF Core 2.2 总是更新“AspNetUsers”表中的“ConcurrencyStamp”、“PasswordHash”?的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core - EF Core 2.2 - 'Point.Boundary' 属于接口类型('IGeometry')

从联接表中删除实体而不影响父级 - EF Core 2.2

从 .NET Core 2.2 迁移到 3.1 后,EF Core 随机抓取 API 请求上的用户表

为啥 EF Core 会生成倒位比较

为啥 SelectMany 不适用于 EF Core Cosmos DB?

EF Core - 为啥“无限”嵌套急切加载?