2

我遇到EF代碼第一次遷移與查找表和外鍵相關的問題。比方說,我有這兩個班在我的代碼:EF代碼首先使用空查找表設置外鍵

public class Test 
{ 
    [Key] 
    public long Id { get; set; } 

    [Required] 
    public string Title { get; set; } 

    [Required, DisplayName("Test type")] 
    public TestType TestType { get; set; } 
} 

public class TestType 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

TestType是一個典型的查找表和我通常填滿他們的在Seed()方法:

context.TestTypes.AddOrUpdate(
    it => it.Name, 
    new TestType() { Name = "Drug" }, 
    new TestType() { Name = "Educational" }, 
    new TestType() { Name = "Other" } 
); 

當我創建表的關係我得到以下遷移:

CreateTable(
    "dbo.TestTypes", 
    c => new 
     { 
      Id = c.Int(nullable: false, identity: true), 
      Name = c.String(), 
     }) 
    .PrimaryKey(t => t.Id); 

AddColumn("dbo.Tests", "TestType_Id", c => c.Int(nullable: false)); 
CreateIndex("dbo.Tests", "TestType_Id"); 
AddForeignKey("dbo.Tests", "TestType_Id", "dbo.TestTypes", "Id", cascadeDelete: true); 

現在,如果我執行過程中的遷移,我會得到一個錯誤,因爲外鍵不能尊重GI事實上,查找表仍然是空的,並且創建的列沒有默認值。

發展我能夠通過簡單地創建兩個遷移來解決這個問題,第一個創建的查找表,第二個設置外鍵。如果我分別運行它們,則第一個之後的Seed方法將填充表格,並且可以調整列創建以從DB中提取值以在創建外鍵之前預填充列,有點像這樣:

AddColumn("dbo.Tests", "TestType_Id", c => c.Int(nullable: false)); 
Sql("UPDATE dbo.Tests SET TestType_Id = (SELECT TOP 1 Id FROM dbo.TestTypes)"); 
CreateIndex("dbo.Tests", "TestType_Id"); 
AddForeignKey("dbo.Tests", "TestType_Id", "dbo.TestTypes", "Id", cascadeDelete: true); 

然後當我運行它時,一切正常。

現在,在生產我沒有相同的奢侈品,因爲所有的遷移都在Seed方法運行之前運行,我總是會遇到同樣的問題。

我知道我可以潛在對生產數據庫運行在階梯順序遷移,以及但這並不能真正解決問題......假設我的一個同事更新他的工作副本並運行遷移,所有將按順序運行,他肯定會遇到錯誤。

+0

TestType不應該創建表嗎? – Neil

回答

0

我不知道你的數據庫的當前狀態,但我會這樣定義

public class Test 
{ 
    [Key] 
    public long Id { get; set; } 

    [Required] 
    public string Title { get; set; } 

    [Required] 
    [ForeignKey("TestType")] 
    public int TestTypeId { get; set; } 

    [DisplayName("Test type")] 
    public virtual TestType TestType { get; set; } 
} 

public class TestType 
{ 
    [Key] 
    public int Id { get; set; } 

    public string Name { get; set; } 
} 

導致以下遷移時不存在的表你的模型。我總是發現描述外鍵顯然更好。

public override void Up() 
{ 
    CreateTable(
     "dbo.Tests", 
     c => new 
      { 
       Id = c.Long(nullable: false, identity: true), 
       Title = c.String(nullable: false), 
       TestTypeId = c.Int(nullable: false), 
      }) 
     .PrimaryKey(t => t.Id) 
     .ForeignKey("dbo.TestTypes", t => t.TestTypeId) 
     .Index(t => t.TestTypeId); 

    CreateTable(
     "dbo.TestTypes", 
     c => new 
      { 
       Id = c.Int(nullable: false, identity: true), 
       Name = c.String(), 
      }) 
     .PrimaryKey(t => t.Id); 
} 

只要Test表是空的,種子應該能正常工作嗎?

+1

是的,問題是'Test'表不是空的...是的,我使用相同的方法來設置外鍵(我不喜歡下劃線的默認值),但上面只是示例代碼。 – Tallmaris