如何遍历 EF Core 迁移中的实体?
How to iterate through entities in EF Core migration?
我正在将 Identity 改装到现有项目中。我已经有 Users
、Roles
和 UserRoles
table,所以这主要是在实际添加 [=47 之前调整 table 和列名=]身份 类,所以他们“接管”了那些table。
我遇到的问题如下。 UserEntity.Id
是一个Guid
,所以我需要从IdentityUser<Guid>
继承UserEntity
。但是 RoleEntity.Id
是一个 long
。 Identity 有一个奇怪的限制,即 User.Id
和 Role.Id
类型必须匹配 - 至少在 AddIdentity<>
扩展方法中使用时。所以我需要将 RoleEntity.Id
的类型更改为 Guid
。由于我已经有许多具有角色的用户,因此我必须调整 UserRoles
table.
现在,为 Roles
创建一组新的 Id 不是问题,它们已播种,所以我只创建了一个新列 Roles.NewId
类型 Guid
并用一些随机值填充它。我还创建了一个相应的列 UserRoles.NewRoleId
(我将在应用 Identity 之前在另一个迁移中重命名它们,以便它们匹配)。我想要的是当 这个特定的 迁移运行时,来自 Roles.NewId
的值被复制到 UserRoles.NewRoleId
,对应于现有的分配。
SQL 命令可能类似于
UPDATE UserRoles U SET NewRoleId = (SELECT NewId FROM Roles WHERE Roles.Id = U.RoleId)
但我在测试中使用内存数据库 (SQLite),在生产中使用 MariaDb,所以SQL 可能不匹配。由于此设置,我已经遇到了一些问题,但是 MariaDb 没有内存中提供程序。因此,如果我可以在某处插入以下循环,我会感觉更安全:
foreach (var ur in UserRoles)
{
ur.NewRoleId = Roles.First(r => r.Id == ur.RoleId).NewId;
}
Save();
现在:
- 我在哪里可以插入那个循环,所以它只在这次迁移之后执行,而不是在每次迁移之后执行?
- 如何处理在下一次迁移中我将重命名一些列,然后删除旧的
Id
和 RoleId
列的情况?
经过调查,我发现只有两个选择。
使用SQL。它不干净,没有 IntelliSense,但它会工作。
对于这种特殊情况,角色是种子,因此 role id
s 在编译时是已知的。因此,可以通过为每个角色创建一个调用并在其中放置一个新的 Guid
(pre-generated 和 hard-coded)来滥用 migrationBuilder.UpdateData
。
migrationBuilder.UpdateData(
table: "UserRoles",
keyColumn: "RoleId",
keyValue: 1L,
column: "NewRoleId",
value: new Guid("11111111-1111-1111-1111-111111111111"));
我正在将 Identity 改装到现有项目中。我已经有 Users
、Roles
和 UserRoles
table,所以这主要是在实际添加 [=47 之前调整 table 和列名=]身份 类,所以他们“接管”了那些table。
我遇到的问题如下。 UserEntity.Id
是一个Guid
,所以我需要从IdentityUser<Guid>
继承UserEntity
。但是 RoleEntity.Id
是一个 long
。 Identity 有一个奇怪的限制,即 User.Id
和 Role.Id
类型必须匹配 - 至少在 AddIdentity<>
扩展方法中使用时。所以我需要将 RoleEntity.Id
的类型更改为 Guid
。由于我已经有许多具有角色的用户,因此我必须调整 UserRoles
table.
现在,为 Roles
创建一组新的 Id 不是问题,它们已播种,所以我只创建了一个新列 Roles.NewId
类型 Guid
并用一些随机值填充它。我还创建了一个相应的列 UserRoles.NewRoleId
(我将在应用 Identity 之前在另一个迁移中重命名它们,以便它们匹配)。我想要的是当 这个特定的 迁移运行时,来自 Roles.NewId
的值被复制到 UserRoles.NewRoleId
,对应于现有的分配。
SQL 命令可能类似于
UPDATE UserRoles U SET NewRoleId = (SELECT NewId FROM Roles WHERE Roles.Id = U.RoleId)
但我在测试中使用内存数据库 (SQLite),在生产中使用 MariaDb,所以SQL 可能不匹配。由于此设置,我已经遇到了一些问题,但是 MariaDb 没有内存中提供程序。因此,如果我可以在某处插入以下循环,我会感觉更安全:
foreach (var ur in UserRoles)
{
ur.NewRoleId = Roles.First(r => r.Id == ur.RoleId).NewId;
}
Save();
现在:
- 我在哪里可以插入那个循环,所以它只在这次迁移之后执行,而不是在每次迁移之后执行?
- 如何处理在下一次迁移中我将重命名一些列,然后删除旧的
Id
和RoleId
列的情况?
经过调查,我发现只有两个选择。
使用SQL。它不干净,没有 IntelliSense,但它会工作。
对于这种特殊情况,角色是种子,因此
role id
s 在编译时是已知的。因此,可以通过为每个角色创建一个调用并在其中放置一个新的Guid
(pre-generated 和 hard-coded)来滥用migrationBuilder.UpdateData
。
migrationBuilder.UpdateData(
table: "UserRoles",
keyColumn: "RoleId",
keyValue: 1L,
column: "NewRoleId",
value: new Guid("11111111-1111-1111-1111-111111111111"));