你得到的類型衝突錯誤,因爲產生的遷移嘗試直接ALTER COLUMN
做對受影響的列的類型更改從Guid
至integer
,這是不可能的,因爲Guid
值不能隱式轉換爲integer
值。
您必須手動修改您的遷移。刪除AlterColumn
行。爲了在不丟失數據的情況下遷移現有的課程標識,您可以暫時重命名現有的Guid
列(添加後綴_Old
),使用正確的新名稱和類型創建新列,並使用正確的值填充關係表中的內容UPDATE
有SELECT
,最後刪除舊的列:
public override void Up()
{
DropForeignKey("dbo.GroupCourses", "Course_Id", "dbo.Courses");
DropIndex("dbo.GroupCourses", new[] { "Course_Id" });
DropPrimaryKey("dbo.Courses");
DropPrimaryKey("dbo.GroupCourses");
//Removed: AlterColumn("dbo.Courses", "Id", c => c.Int(nullable: false, identity: true));
RenameColumn("dbo.Courses", "Id", "Id_Old"); //Added
AddColumn("dbo.Courses", "Id", c => c.Int(nullable: false, identity: true)); //Added
//Removed: AlterColumn("dbo.GroupCourses", "Course_Id", c => c.Int(nullable: false));
RenameColumn("dbo.GroupCourses", "Course_Id", "Course_Id_Old"); //Added
AddColumn("dbo.GroupCourses", "Course_Id", c => c.Int(nullable: false)); //Added
Sql(@"UPDATE gc SET gc.Course_Id = c.Id "
+ "FROM dbo.GroupCourses as gc "
+ "INNER JOIN dbo.Courses as c ON gc.Course_Id_Old = c.id_Old"); //Added
DropColumn("dbo.GroupCourses", "Course_Id_Old"); //Added
DropColumn("dbo.Courses", "Id_Old"); //Added
AddPrimaryKey("dbo.Courses", "Id");
AddPrimaryKey("dbo.GroupCourses", new[] { "Group_Id", "Course_Id" });
CreateIndex("dbo.GroupCourses", "Course_Id");
AddForeignKey("dbo.GroupCourses", "Course_Id", "dbo.Courses", "Id", cascadeDelete: true);
}
標誌着我在我的代碼與意見//Added
和//Removed
改變了線路。其餘代碼是在模型中將屬性類型更改爲int
後使用Add-Migration
生成的遷移中的原始代碼。您只需填寫UPDATE
關係表中列中的值。 Courses.Id
列中的值將自動生成,因爲它是identity
列。
您還應該計算Down()
方法並實施相反的過程,或者如果您真的永遠不會將數據庫降級到先前的遷移,就會保持原樣。
您也可以通過拆分遷移和播種機之間的代碼來實現此目的。從概念上講,它會更加正確,因爲您應該使用遷移進行架構修改,並使用播種器進行數據修改。但是我認爲這樣更容易,只需要一次遷移,而使用播種器的方法則需要兩次遷移:一次包含上述代碼,除了UPDATE
和刪除_Old
列的句子,以及另一個刪除_Old
列。 UPDATE
部分將在播種機中實施。
警告:UPDATE
語句中包含的SQL代碼與Sql Server
一起使用,但可能無法與其他數據庫引擎一起使用。這是使用遷移而不是播種機的另一個缺點。
您可以通過'Seed()'方法進行遷移以添加一個CourseTemp,它將您的舊課程表中的所有數據插入到Temp中?那麼你可以做另一次遷移來刪除原始課程並重命名CoureseTemp類/表? – Bwolfing