[英]EF Core Migration (code first): How do I add a new non-null column and populate existing records with unique values not based on data in other fields?
我目前有一个实体:
我想添加一个非空字段/列,并且我想用唯一值(例如 GUID)填充每条记录:
我的困惑是如何用满足 UNIQUE 约束的数据填充现有行。 我可以执行以下迁移之一,但它们都使用相同的 GUID 填充所有现有行:
// OPTION 1
// 😢 Uses same GUID for all rows
migrationBuilder.AddColumn<string>(
name: "PublicId",
table: "Customers",
nullable: false,
defaultValue: Guid.NewGuid().ToString());
migrationBuilder.CreateIndex(
name: "IX_Customers_PublicId",
table: "Customers",
column: "PublicId",
unique: true);
// OPTION 2
migrationBuilder.AddColumn<string>(
name: "PublicId",
table: "Customers",
nullable: false,
defaultValue: "");
// 😢 Still uses same GUID for all rows
migrationBuilder.Sql($"UPDATE Customers SET PublicId = '{Guid.NewGuid()}' WHERE PublicId = ''");
migrationBuilder.CreateIndex(
name: "IX_Customers_PublicId",
table: "Customers",
column: "PublicId",
unique: true);
是否可以在迁移中做一些事情,用唯一值填充每个现有行?
如果它很重要,引擎盖下的数据库是 SQLite。
更新
我只是以 GUID 为例。 在我的例子中,它是另一个应用程序 function 为这个新字段/列生成唯一 ID。
换句话说,我不能按照数据库(例如NEWID()
)为我生成唯一 ID。
您可以使用defaultValueSql
设置自定义 SQL 表达式和newid()
作为表达式(用于 SQL 服务器)。
migrationBuilder.AddColumn<string>(
name: "PublicId",
table: "Customers",
nullable: false,
defaultValueSql: "newid()");
Sqlite 应该有类似的东西。
您需要将其添加为可为空,让您的应用程序设置 id,然后将其更改为非 null。
至于你是否可以在单个 EF Core“ApplyMigrations()”过程中做到这一切——我怀疑如果你足够坚定的话。 例如,如果您在应用程序中使用 EF Core 应用迁移,那么这是我想到的一种方法:
// check to see if we need to apply this migration - it may have been applied already on a previous app startup.
var pendingMigrations = await dbContext.Database.GetPendingMigrationsAsync();
var applyFirstMigration = IsMigrationIdPending(pendingMigrations, "Your-Migration-Id-That-Adds-Nullable-Column");
// Note that DbContext.Migrate() builds on top of the `IMigrator` service, which can be used for more advanced scenarios.
var migrator = myDbContext.GetInfrastructure().GetService<IMigrator>();
if(applyFirstMigration)
{
// apply the migrations only up to the one that adds the nullable column
await migrator.MigrateAsync("Your-Migration-Id-That-Adds-Nullable-Column", CancellationToken);
}
var applySecondMigration = IsMigrationIdPending(pendingMigrations, "Your-Migration-Id-That-Does-Nothing");
if(applySecondMigration)
{
// use whatever foo you need to set these records in the database to values provided here by your application - this could be executing a script via ado net, another dbcontext, this dbontext (not sure whether that will work), or even - passing the ids statically (static property) on your "empty" ef core migration, and have that ef core migration generate SQL to execute when it is applied etc)
await UpdateRecordsWithNull();
await migrator.MigrateAsync("Your-Migration-Id-That-Does-Nothing", CancellationToken); // makes sure this migration is applied so we won't ever run this step again.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.