我決定將一列從不可為空的列更改為可空的列。這里沒有問題。我將屬性更改為“?” 在型別(DateTime=> DateTime?)中,生成的遷移是可以的。
不過,我想將被視為“null”的值更改為真正的 null。意思是,將值更改0001-01-01 00:00:00為null。
我創建了一個擴展方法,可以正確生成上下的 SQL 代碼。我在 .in 中的列更改之后Up和之前執行了此操作Down。
執行時出現問題,Up因為我的擴展方法中的 SQL 在應用列更改的更改之前執行。
無論如何在執行此陳述句之前強制應用更改?(參見FIXME代碼中可以插入代碼的位置。可能有兩個位置。)
擴展類
public static class MigrationsCorrections
{
public static OperationBuilder<SqlOperation> ChangeDateToNullable(this MigrationBuilder migrationBuilder, string table, string column)
{
//FIXME: Either having a call here this to force previous changes to be applied
return migrationBuilder.Sql($"UPDATE {table} SET {column} = null WHERE {column} = '0001-01-01 00:00:00';");
}
public static OperationBuilder<SqlOperation> ChangeDateToNotNullable(this MigrationBuilder migrationBuilder, string table, string column)
{
return migrationBuilder.Sql($"UPDATE {table} SET {column} = '0001-01-01 00:00:00' WHERE {column} = null;");
}
}
遷移類
// IMPORTATION OF THE EXTENSION CLASS
public partial class MetaPersonBirthDateNullable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "BirthDay",
table: "MetaPersons",
type: "TEXT",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "TEXT");
//FIXME: Either having a call here this to force previous changes to be applied
migrationBuilder.ChangeDateToNullable("MetaPersons", "BirthDay");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.ChangeDateToNotNullable("MetaPersons", "BirthDay");
migrationBuilder.AlterColumn<DateTime>(
name: "BirthDay",
table: "MetaPersons",
type: "TEXT",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "TEXT",
oldNullable: true);
}
}
遷移生成的 SQL
BEGIN TRANSACTION;
UPDATE MetaPersons SET BirthDay = null WHERE BirthDay = '0001-01-01 00:00:00';
CREATE TABLE "ef_temp_MetaPersons" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_MetaPersons" PRIMARY KEY AUTOINCREMENT,
"BirthDay" TEXT NULL,
"DeathDay" TEXT NULL,
"ExternalId" TEXT NULL,
"MetaSource" TEXT NULL,
"Name" TEXT COLLATE NOCASE NULL,
"Professions" TEXT NULL
);
INSERT INTO "ef_temp_MetaPersons" ("Id", "BirthDay", "DeathDay", "ExternalId", "MetaSource", "Name", "Professions")
SELECT "Id", "BirthDay", "DeathDay", "ExternalId", "MetaSource", "Name", "Professions"
FROM "MetaPersons";
COMMIT;
PRAGMA foreign_keys = 0;
BEGIN TRANSACTION;
DROP TABLE "MetaPersons";
ALTER TABLE "ef_temp_MetaPersons" RENAME TO "MetaPersons";
COMMIT;
PRAGMA foreign_keys = 1;
BEGIN TRANSACTION;
CREATE UNIQUE INDEX "IX_MetaPersons_ExternalId_MetaSource" ON "MetaPersons" ("ExternalId", "MetaSource");
CREATE INDEX "IX_MetaPersons_Name" ON "MetaPersons" ("Name");
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220309145323_MetaPerson.BirthDate Nullable', '6.0.2');
COMMIT;
如我們所見,該UPDATE陳述句的順序不正確
編輯 1
我嘗試按照Microsoft Custom Migration使用 MigrationOperation 類,但我得到...
當表 'MetaPersons' 的重建掛起時,將嘗試型別為 'ChangeDateToNullable' 的操作。資料庫可能未處于預期狀態。查看此遷移生成的 SQL 以幫助診斷任何故障。考慮將這些操作移至后續遷移。
這個特殊的解決方案是我認為的,有第二次遷移,但這不是我想要的,因為這些更改是聯系在一起的。
uj5u.com熱心網友回復:
從檔案Using MigrationBuilder.Sql():
當陳述句必須是 SQL 批處理中的第一個或唯一一個時,請使用 EXEC 函式。可能還需要解決冪等遷移腳本中的決議器錯誤,這些錯誤可能在表中當前不存在參考的列時發生。
所以最好創建兩個遷移,一個用于 ALTER,另一個用于 UPDATE。
uj5u.com熱心網友回復:
我解決了向 MigrationOperations 方向尋求的問題。我覆寫了IMigrationsSqlGenerator.
為了有一個通用的解決方案,我創建了一個新的資料庫專案,其中包括這個新專案以及MigrationsSqlGenerator將日期列值從/更改為 null 所需的類。我還添加了兩個類來執行任何尊重順序的 SQL 代碼,從而能夠在更改列的值后對其進行更改。而這一切,都在同一次遷移中。
有關完整解決方案,請參閱https://github.com/djon2003/com.cyberinternauts.csharp.Database。
以及相關文章的https://www.codeproject.com/Articles/5327089/Executing-SQL-code-within-EntityFrameworkCore-migr。
最終生成的 SQL 代碼:
BEGIN TRANSACTION;
CREATE TABLE "ef_temp_MetaPersons" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_MetaPersons" PRIMARY KEY AUTOINCREMENT,
"BirthDay" TEXT NULL,
"DeathDay" TEXT NULL,
"ExternalId" TEXT NULL,
"MetaSource" TEXT NULL,
"Name" TEXT COLLATE NOCASE NULL,
"Professions" TEXT NULL
);
INSERT INTO "ef_temp_MetaPersons" ("Id", "BirthDay", "DeathDay", "ExternalId", "MetaSource", "Name", "Professions")
SELECT "Id", "BirthDay", "DeathDay", "ExternalId", "MetaSource", "Name", "Professions"
FROM "MetaPersons";
COMMIT;
PRAGMA foreign_keys = 0;
BEGIN TRANSACTION;
DROP TABLE "MetaPersons";
ALTER TABLE "ef_temp_MetaPersons" RENAME TO "MetaPersons";
COMMIT;
PRAGMA foreign_keys = 1;
BEGIN TRANSACTION;
CREATE UNIQUE INDEX "IX_MetaPersons_ExternalId_MetaSource" ON "MetaPersons" ("ExternalId", "MetaSource");
CREATE INDEX "IX_MetaPersons_Name" ON "MetaPersons" ("Name");
UPDATE "MetaPersons" SET "BirthDay" = null WHERE "BirthDay" = '0001-01-01 00:00:00';
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220309145323_MetaPerson.BirthDate Nullable', '6.0.2');
COMMIT;
如您所見,現在 UPDATE 陳述句位于列更改之后
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/442098.html
上一篇:如何在沒有括號和特定列(Python)的情況下將值從sqlite插入到excel中?
下一篇:SQLite視窗函式
