2017-01-27 89 views
1

is documented並且已知EF核心遷移腳本不支持刪除列。所以我正在嘗試手動完成。EF Core - 刪除列解決方案(sqlite)

我的模型類:

class Master 
{ 
    public int Id { get; set; } 
    public string ToBeDeleted { get; set; } 
} 

class Detail 
{ 
    public int Id { get; set; } 

    public Master Master { get; set; } 
} 

我的背景:

​​

我創建了一個遷移腳本,然後運行下面的程序來創建數據庫文件,並添加幾個行:

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var context = new Context()) 
     { 
      context.Database.Migrate(); 
      if(!context.Masters.Any()) 
      { 
       var master = new Master {ToBeDeleted = "Some string"}; 
       context.Add(master); 
       context.Add(new Detail {Master = master}); 
       context.SaveChanges(); 
      } 
     } 
    } 
} 

我刪除ToBeDeletedMaster類別和基因的性質額定第二遷移腳本,它生成非常簡單的代碼,不工作,因爲它只會在未來得到支持:

protected override void Up(MigrationBuilder migrationBuilder) 
{ 
    migrationBuilder.DropColumn(
     name: "ToBeDeleted", 
     table: "Masters"); 
} 

protected override void Down(MigrationBuilder migrationBuilder) 
{ 
    migrationBuilder.AddColumn<string>(
     name: "ToBeDeleted", 
     table: "Masters", 
     nullable: true); 
} 

所以它的時候,我寫我自己的東西,這是什麼我已經試過:

protected override void Up(MigrationBuilder migrationBuilder) 
{ 
    migrationBuilder.Sql("PRAGMA foreign_keys=OFF"); 
    migrationBuilder.CreateTable(
     name: "NEW_Masters", 
     columns: table => new 
     { 
      Id = table.Column<int>(nullable: false) 
       .Annotation("Sqlite:Autoincrement", true), 
     }, 
     constraints: table => 
     { 
      table.PrimaryKey("PK_Masters", x => x.Id); 
     }); 
    migrationBuilder.Sql("INSERT INTO NEW_Masters SELECT Id FROM Masters;"); 
    migrationBuilder.DropTable("Masters"); 
    migrationBuilder.RenameTable("NEW_Masters", newName: "Masters"); 
    migrationBuilder.Sql("PRAGMA foreign_keys=OFF"); 
} 

然而,這將導致context.Database.Migrate()拋出異常:

型「Microsoft.Data.Sqlite.SqliteException」 未處理的異常發生在百萬分之一oft.EntityFrameworkCore.Relational.dll

附加信息:SQLite錯誤19:'FOREIGN KEY約束 失敗'。

最後,問題:如何在移植腳本中手動刪除列?

UPDATE

以下建議我在討論了,我以前Script-Migration來從遷移腳本的SQL和得到這個:

CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
    "MigrationId" TEXT NOT NULL CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY, 
    "ProductVersion" TEXT NOT NULL 
); 

CREATE TABLE "Masters" (
    "Id" INTEGER NOT NULL CONSTRAINT "PK_Masters" PRIMARY KEY AUTOINCREMENT, 
    "ToBeDeleted" TEXT 
); 

CREATE TABLE "Details" (
    "Id" INTEGER NOT NULL CONSTRAINT "PK_Details" PRIMARY KEY AUTOINCREMENT, 
    "MasterId" INTEGER, 
    CONSTRAINT "FK_Details_Masters_MasterId" FOREIGN KEY ("MasterId") REFERENCES "Masters" ("Id") ON DELETE RESTRICT 
); 

CREATE INDEX "IX_Details_MasterId" ON "Details" ("MasterId"); 

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") 
VALUES ('20170127204056_Migration1', '1.1.0-rtm-22752'); 

INSERT INTO Masters (ToBeDeleted) VALUES ("ASDF"); --I've added this line manually for test only 

INSERT INTO Details (MasterId) VALUES (1); --I've added this line manually for test only 

PRAGMA foreign_keys="0"; 

CREATE TABLE "NEW_Masters" (
    "Id" INTEGER NOT NULL CONSTRAINT "PK_Masters" PRIMARY KEY AUTOINCREMENT 
); 

INSERT INTO NEW_Masters SELECT Id FROM Masters;; 

DROP TABLE "Masters"; 

ALTER TABLE "NEW_Masters" RENAME TO "Masters"; 

PRAGMA foreign_keys="1"; 

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") 
VALUES ('20170127204851_Migration2', '1.1.0-rtm-22752'); 

和腳本工作正常。例外情況是由EF執行的某些外鍵檢查。

+0

哪一行引發異常? –

+0

@ CL.'context.Database.Migrate()' –

回答

0

EF core developers指出PRAGMA foreign_keys=0在SQLite事務中不起作用,並且建議使用migrationBuilder.Sql方法來禁止使用事務。

於是我想出了:

protected override void Up(MigrationBuilder migrationBuilder) 
    { 
     migrationBuilder.CreateTable(
      name: "NEW_Masters", 
      columns: table => new 
      { 
       Id = table.Column<int>(nullable: false) 
        .Annotation("Sqlite:Autoincrement", true), 
      }, 
      constraints: table => 
      { 
       table.PrimaryKey("PK_Masters", x => x.Id); 
      }); 
     migrationBuilder.Sql("INSERT INTO NEW_Masters SELECT Id FROM Masters;"); 
     migrationBuilder.Sql("PRAGMA foreign_keys=\"0\"", true); 
     migrationBuilder.Sql("DROP TABLE Masters", true); 
     migrationBuilder.Sql("ALTER TABLE NEW_Masters RENAME TO Masters", true); 
     migrationBuilder.Sql("PRAGMA foreign_keys=\"1\"", true); 
    } 

而且它的伎倆。

0

對於懶惰者,我所做的是手動刪除解決方案中的遷移,然後sqlite數據庫添加了遷移。當這個討厭的錯誤出現時,它不能放棄,註釋掉up方法的正文,就像這樣:在生成的腳本中。然後更新db。當我將引用對象類型SocialMediaLinks添加到我的用戶時,它生成了一個fk。這不是一個適合所有人的解決方案,因爲它可能會導致數據丟失。也刪除導致fk依賴性的CLASS ENTITY。

//generated migration: 

protected override void Up(MigrationBuilder migrationBuilder) 
     { 
      //comment out-- 
      //migrationBuilder.DropColumn(
      // name: "SocialMediaLinks", 
      // table: "ProfileUserVM"); 

      //migrationBuilder.DropColumn(
      // name: "SocialMediaLinks", 
      // table: "AspUsers"); 
     } 

     protected override void Down(MigrationBuilder migrationBuilder) 
     { 
      migrationBuilder.AddColumn<string>(
       name: "SocialMediaLinks", 
       table: "ProfileUserVM", 
       nullable: true); 

      migrationBuilder.AddColumn<string>(
       name: "SocialMediaLinks", 
       table: "AspUsers", 
       nullable: true); 
     } 
相關問題