2014年4月1日 星期二

ASP.NET MVC 4 遇到「參數 @objname 模稜兩可或是所宣告的 @objtype (COLUMN) 有誤。」 之解決方案

今天 MVC 在做 code first 自動移轉時遇到「參數 @objname 模稜兩可或是所宣告的 @objtype (COLUMN) 有誤。」,如下圖


怪了,平常改動資料欄位,也不會產生錯誤,檢查了一下,我的程式碼只是將一對多關聯改成一對一 ( 以下為示意 ):
public class A
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid AId { get; set; }

        public string Name { get; set; }

        // 修改前
        // public ICollection<B> B { get; set; }

        // 修改後
        public B B { get; set; }
    }

    public class B
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid BId { get; set; }

        // ...
    }

後來上網搜尋了一下, EF CodeFirst: Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong 有說明這是因為欄位在 rename 時發生錯誤,這不太可能吧!我應該只是將 B 的 A_AId 轉移到 A 的 B_BId,好像沒有 rename 的動作。

接著我將它的移轉檔案叫出來,在「套件管理器主控台」使用指令 Add-Migration Test 將檔案產出,這才發現問題:
public partial class Test : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.B", "A_AId", "dbo.A");
        DropIndex("dbo.B", new[] { "A_AId" });
        RenameColumn(table: "dbo.A", name: "A_AId", newName: "B_BId");
        AddForeignKey("dbo.A", "B_BId", "dbo.B", "BId");
        CreateIndex("dbo.A", "B_BId");
    }
    
    public override void Down()
    {
        DropIndex("dbo.A", new[] { "B_BId" });
        DropForeignKey("dbo.A", "B_BId", "dbo.B");
        RenameColumn(table: "dbo.A", name: "B_BId", newName: "A_AId");
        CreateIndex("dbo.B", "A_AId");
        AddForeignKey("dbo.B", "A_AId", "dbo.A", "AId");
    }
}

Up 在 Migration ( 轉移 ) 時,會執行,而如果發生錯誤則會使用 Down RollBack。

問題就是發生在 Up 的第三行 - RenameColumn( ... ),在 A 資料表並無 B_BId 欄位,但居然要把 B_BId 命名成為 A_AId ? 所以這一看就是有問題,重新執行後問題依舊存在。

所以建議先把一對多關連註解掉運行 API,再將一對一關聯加入在運行 API 後就會正常,或者你也可以就移轉檔案改動:
public override void Up()
{
    DropForeignKey("dbo.B", "A_AId", "dbo.A");
    DropIndex("dbo.B", new[] { "A_AId" });
    DropColumn("dbo.B", "A_AId");

    AddColumn("dbo.A", "B_BId", c => c.Guid());
    AddForeignKey("dbo.A", "B_BId", "dbo.B", "BId");
    CreateIndex("dbo.A", "B_BId");
}

前者解決方法會比自己修改移轉檔案來得好,因為你還是要看程式碼找出錯誤在哪裡,比較花時間。

沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...