2017-06-22 183 views
0

我正在嘗試創建2個表。一個用於商店和一個用於收款機。收銀機具有複合鍵:身份證+ ShopId添加或更新EF複合主鍵違規

這裏是一個模式:

public class Shop 
{ 
    [Key] 
    public int Id { get; set; } 
    public string ShopName { get; set; } 
} 

public class CashRegister 
{ 
    [Key, Column(Order = 0)] 
    public int Id { get; set; } 
    public string CashRegisterName { get; set; } 

    [ForeignKey("ShopId")] 
    public Shop Shop { get; set; } 

    [Key, Column(Order = 1)] 
    public int ShopId { get; set; } 
} 

這裏是移民的樣子:

 CreateTable(
      "dbo.CashRegisters", 
      c => new 
       { 
        Id = c.Int(nullable: false), 
        ShopId = c.Int(nullable: false), 
        CashRegisterName = c.String(), 
       }) 
      .PrimaryKey(t => new { t.Id, t.ShopId }) 
      .ForeignKey("dbo.Shops", t => t.ShopId, cascadeDelete: true) 
      .Index(t => t.ShopId); 

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

這裏是拋出主鍵衝突異常的代碼:

 var context = new Model(); 

     var shops = new List<Shop> 
     { 
      new Shop() { ShopName = "First shop" }, 
      new Shop() { ShopName = "Second shop" } 
     }; 

     context.Shops.AddOrUpdate(shops.ToArray()); 
     context.SaveChanges(); 

     var cashRegisters = new List<CashRegister>(); 

     foreach (var shop in shops) 
     { 
      cashRegisters.Add(new CashRegister() 
      { 
       CashRegisterName = "First cash register", 
       ShopId = shop.Id 
      }); 

      cashRegisters.Add(new CashRegister() 
      { 
       CashRegisterName = "Second cash register", 
       ShopId = shop.Id 
      }); 
     } 

     context.CashRegisters.AddOrUpdate(a => new { a.Id, a.ShopId }, cashRegisters.ToArray()); 
     context.SaveChanges(); 
     //primary key violation exception on line above 

現在很明顯,收銀機在創建時有0個Id 。 我得到的例外是:

"Violation of PRIMARY KEY constraint 'PK_dbo.CashRegisters'. Cannot insert duplicate key in object 'dbo.CashRegisters'. The duplicate key value is (0, 1).\r\nThe statement has been terminated."

我嘗試添加[DatabaseGenerated(DatabaseGeneratedOption.Identity)]CashRegister.Id 後來我得到另一個異常{"Cannot insert the value NULL into column 'Id', table 'TestCompositeKeys.dbo.CashRegisters'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."},這是奇怪的,因爲Id甚至沒有空。

誰能告訴我我做錯了什麼,或者我該如何解決這個問題?謝謝

+0

也許在你的'CashRegister'中,你需要分配'Shop'屬性(對象),而不僅僅是外鍵。 –

+1

@JoseLuis謝謝你的評論,但它沒有幫助。我添加了一條異常消息。我相信用Id(0,1)插入第一個記錄,然後用Id(0,1)插入第二個記錄,這導致異常。如果它不是一個複合鍵它會工作正常 – netaholic

+1

我想了解*爲什麼*你使用複合主鍵。通常,在極少數情況下,密鑰的每個部分都將由其他現有實體確定,因此複合密鑰永遠不會有自動生成的組件。 – grek40

回答

2

設置CashRegister.Id自動增量應該實際上工作。

public class CashRegister 
{ 
    [Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    // ... 

要考慮的另一件事是AddOrUpdate聲明。由於Id只會在實際插入時分配,因此您無法通過Id真正比較條目。相反,你可以嘗試以下方法:

context.CashRegisters.AddOrUpdate(a => new { a.ShopId, a.CashRegisterName }, cashRegisters.ToArray()); 

它只會使用初始化的性能進行比較,將真正防止再插入,而與a.Id, a.ShopId執行種子第二遍的時候,你可能會得到重複。

+0

感謝您使用'AddOrUpdate'提示,您是對的 – netaholic

1

在這裏,這

foreach (var shop in shops) 
     { 
      cashRegisters.Add(new CashRegister() 
      { 
       CashRegisterName = "First cash register", 
       ShopId = shop.Id 
      }); 

      cashRegisters.Add(new CashRegister() 
      { 
       CashRegisterName = "Second cash register", 
       ShopId = shop.Id 
      }); 
     } 

代碼將插入4一下現金出納機對象。兩個商店都有兩個。當ShopId設置爲主鍵時,則對於CashRegister表不能有兩次相同的ShopId。

解決方案是爲每個Shop對象插入一個CashRegister對象或從ShopId中刪除主約束。

相關問題