数据库数据初始化迁移

本文介绍了如何使用Entity Framework(EF)进行数据库初始化和迁移。重点在于`Add-Migration`和`Update-Database`命令的使用,以及在初始化数据时需要注意User、Role、UserRole的填充,特别是`NormalizedEmail`和`NormalizedUserName`字段。还提到了数据库迁移历史记录对后续迁移的影响及解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 迁移基本步骤参考
  2. dotnet ef migrations add {migration name} -p {dbcontext project} -s {host startup project}
    1. 这里的migration name,我以AddData为例:
    2. 发现Migrations文件夹下多了两个文件20180610024345_AddData.cs20180610024345_AddData.Designer.cs
    3. 这边我们只关注前一个文件,里面有一个类继承自Migration,它有两个函数UpDown,且都是空的,熟悉ef的人对这两个函数的大体作用应该比较清楚
    4. 数据要初始化主要使用到Up函数的实参MigrationBuilder migrationBuilder,查看源码,这个函数提供了很多有用的函数InsertData UpdateData
  3. 废话不多说,直接上代码

    public partial class AddData : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            extra(migrationBuilder);
        }
    
        private void extra(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.InsertRole(new IdentityRole() { Id = "master_id", Name = "Master", NormalizedName = "Master" });
            migrationBuilder.InsertRole(new IdentityRole() { Id = "admin_id", Name = "Administrator", NormalizedName = "Administrator" });
            migrationBuilder.InsertRole(new IdentityRole() { Id = "vistor_id", Name = "Vistor", NormalizedName = "Vistor" });
    
            var pwdHasher = new PasswordHasher<IdentityUser>();
            var user = new IdentityUser("DaneSpirit")
            {
                Id = "dane_id",
                NormalizedUserName = "DaneSpirit",
                SecurityStamp = Guid.NewGuid().ToString()
            };
            user.PasswordHash = pwdHasher.HashPassword(user, "danespirit");
            migrationBuilder.InsertSimpleUser(user);
    
            user = new IdentityUser("TestUser")
            {
                Id = "testuser_id",
                NormalizedUserName = "TestUser",
                SecurityStamp = Guid.NewGuid().ToString()
            };
            user.PasswordHash = pwdHasher.HashPassword(user, "test");
            migrationBuilder.InsertSimpleUser(user);
    
            migrationBuilder.InsertUserRole(new IdentityUserRole<string>() { UserId = "dane_id", RoleId = "master_id" });
            migrationBuilder.InsertUserRole(new IdentityUserRole<string>() { UserId = "testuser_id", RoleId = "vistor_id" });
        }
    
        protected override void Down(MigrationBuilder migrationBuilder)
        {
    
        }
    }
    1. 我的项目使用了Asp.Net Core Identity,这里我对User、Role、UserRole作了一些基本的初始化,InsertRole InsertSimpleUser InsertUserRole是扩展方法

      namespace Microsoft.EntityFrameworkCore.Migrations
      {
          static class MigrationBuilderExtensions
          {
              public static OperationBuilder<InsertDataOperation> InsertRole(this MigrationBuilder builder, IdentityRole role)
              {
                  var insertDataOperation = new InsertDataOperation()
                  {
                      Table = "aspnetroles",
                      Schema = null,
                      Columns = new[] { "id", "name", "NormalizedName", "concurrencystamp" },
                      Values = new object[,] { { role.Id, role.Name, role.NormalizedName, role.ConcurrencyStamp } }
                  };
                  builder.Operations.Add(insertDataOperation);
                  return new OperationBuilder<InsertDataOperation>(insertDataOperation);
              }
      
              public static OperationBuilder<InsertDataOperation> InsertSimpleUser(this MigrationBuilder builder, IdentityUser user)
              {
                  var insertDataOperation = new InsertDataOperation()
                  {
                      Table = "aspnetusers",
                      Schema = null,
                      Columns = new[] { "id", "username", "NormalizedUserName", "passwordhash", "EmailConfirmed", "AccessFailedCount", "LockoutEnabled", "PhoneNumberConfirmed", "TwoFactorEnabled", "concurrencystamp", "SecurityStamp" },
                      Values = new object[,] { { user.Id, user.UserName, user.NormalizedUserName, user.PasswordHash, false, 0, false, false, false, user.ConcurrencyStamp, user.SecurityStamp } }
                  };
                  builder.Operations.Add(insertDataOperation);
                  return new OperationBuilder<InsertDataOperation>(insertDataOperation);
              }
      
              public static OperationBuilder<InsertDataOperation> InsertUserRole(this MigrationBuilder builder, IdentityUserRole<string> userRole)
              {
                  var insertDataOperation = new InsertDataOperation()
                  {
                      Table = "aspnetuserroles",
                      Schema = null,
                      Columns = new[] { "userid", "roleid" },
                      Values = new object[1, 2] { { userRole.UserId, userRole.RoleId } }
                  };
                  builder.Operations.Add(insertDataOperation);
                  return new OperationBuilder<InsertDataOperation>(insertDataOperation);
              }
          }
      }
    2. 扩展方法的使用参考了MigrationBuilder的源码

    3. 特别注意1:User Role的查询索引都是Normalized*Name,所以咱们的初始化中必须要填充这个字段,否则在后期验证过程中会出现找不到该用户的Exception
    4. 特别注意2:UserPasswordHash必须是要经过PasswordHasher.HashPassword函数处理过的,否则也没法在运行时验证通过
  4. dotnet ef database update -p {dbcontext project} -s {host startup project} 不出意外,迁移顺利进行
  5. 这里说句题外话,迁移后数据库中会出现一个非自定义表__efmigrationshistory,它是迁移的历史记录,一般情况下,在4中迁移成功后,再次调用4中的命令是不会执行的,主要原因是4的迁移记录已经记录在数据库中,不会发生二次迁移。如果要使4中的命令再次可执行,一个简单的方法是在数据库中将最新的一条迁移历史记录删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值