2017-06-22 4 views
0

Ich versuche, 2 Tabellen zu erstellen. Einer für Geschäfte und einer für Kassen. Kassen haben Verbundschlüssel: Id + ShopIDEF Composite-Primärschlüsselverletzung auf AddOrUpdate

Hier ist ein Modell:

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; } 
} 

Hier ist, wie die Migration wie folgt aussieht:

 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); 

Und hier ist der Code, der primäre Schlüsselverletzung Ausnahme auslöst :

 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 

Jetzt offensichtlich haben Kassen eine 0 als Id bei der Erstellung . Die Ausnahme, die ich bekommen ist:

"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."

Ich versuchte [DatabaseGenerated(DatabaseGeneratedOption.Identity)]-CashRegister.Id Zugabe, aber dann bekomme ich eine weitere Ausnahme {"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."}, die seltsam ist, da Id nicht einmal NULL-Werte zulässt.

Kann mir jemand sagen, was mache ich falsch oder wie behebe ich das? Danke

+0

Vielleicht müssen Sie in Ihrem 'CashRegister' die Eigenschaft' Shop' (das Objekt) und nicht nur den Fremdschlüssel zuweisen. –

+1

@JoseLuis danke für den Kommentar, aber es hat nicht geholfen. Ich habe eine Ausnahmebedingung hinzugefügt, die ich erhalte. Ich glaube, ein erster Datensatz wird mit Id (0, 1) eingefügt, dann wird der zweite mit Id (0,1) eingefügt, was zu einer Ausnahme führt. Wenn es kein zusammengesetzter Schlüssel wäre, hätte es gut funktioniert – netaholic

+1

Ich möchte verstehen, warum Sie einen zusammengesetzten Primärschlüssel verwenden. Normalerweise wird in den seltenen Fällen, in denen es erforderlich ist, jeder Teil des Schlüssels von anderen vorhandenen Entitäten bestimmt, so dass ein zusammengesetzter Schlüssel niemals eine automatisch generierte Komponente hätte. – grek40

Antwort

2

Die Einstellung der CashRegister.Id Auto-Inkrement sollte eigentlich funktionieren.

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

Die andere Sache zu prüfen ist die AddOrUpdate Aussage. Da Id nur zugewiesen wird, wenn es tatsächlich eingefügt wird, können Einträge nicht wirklich anhand der ID verglichen werden. Stattdessen könnten Sie versuchen, die folgenden:

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

Es nur initialisierte Eigenschaften für den Vergleich zu verwenden und wirklich Reinsertion verhindern, während mit a.Id, a.ShopId würden Sie wahrscheinlich Duplikate erhalten, wenn die Samen zweiten Mal ausgeführt wird.

+0

Danke für 'AddOrUpdate' Tipp, Sie haben Recht – netaholic

1

Dieser Code

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 
      }); 
     } 

wird 4 Cashregister Objekt einfügen. jeweils zwei für beide Shops. Wenn ShopId als Primärschlüssel festgelegt ist, kann die Tabelle "CashRegister" die gleiche ShopId nicht zweimal enthalten.

Die Lösung ist entweder ein CashRegister Objekt für jedes Shop-Objekt einfügen oder primäre Constraint von ShopId entfernen.

Verwandte Themen