2015-04-18 17 views
6

Ho iniziato con C# e volevo creare il mio DB.Violazione della chiave primaria Entity Framework Code First

ho due modelli

public class AModel 
{ 
    public Guid ID { get; private set; } 
    public string Name { get; set; } 
    public int Count { get; set; } 
    public AModel() 
    { 
     this.ID = Guid.NewGuid(); 
    } 
} 

public class BModel 
{ 
    public Guid ID { get; private set; } 
    public string Name { get; set; } 
    public AModel Model { get; set; } 
    public BModel() 
    { 
     this.ID = Guid.NewGuid(); 
    } 
} 

Quando cerco di salvare BModel a DB, ottengo questo errore:

Violation of PRIMARY KEY constraint 'PK_dbo.AModels'. Cannot insert duplicate key in object 'dbo.AModels'. The duplicate key value is (48ee1711-8da4-46c1-a714-19e985211fed).\r\nThe statement has been terminated.

ho pensato che sarebbe stato risolto con questo

modelBuilder.Entity<BModel>().HasRequired(t => t.Model).WithMany(); 

ma sembra che io sia completamente perso. Qualcuno potrebbe aiutarmi con questo semplice esempio?

+0

Il messaggio di errore è criptico perché le probabilità di duplicati le chiavi con un Guid sono astronomicamente improbabili. Ciò che sospetto, tuttavia, è che a causa della mappatura errata, si stia tentando di creare più chiavi esterne identiche. Cosa succede se si utilizza 'modelBuilder.Entity () .HasRequired (t => t.Model) .WithMany(). Map (x => {x.ToTable (" BAs "); x.MapLeftKey (" BId ") ; x.MapRightKey ("AId");}); '? –

+1

Non sto creando una nuova istanza di AModel durante la creazione di BModel, ma invece, sto scegliendo un'istanza di AModel già creata da Combobox. Voglio solo creare riferimenti da BModel a AModel. – xfrog

+0

Come funzionerà? stai creando un nuovo GUID ogni volta che viene creato un nuovo modello. e c'è un set privato.Quando recupera una modalità dai dati, come assegnerà un valore all'ID? –

risposta

11

Il tuo commento rivela informazioni vitali. Quando aggiungi AModel dalla tua casella combinata al tuo BModel, a quel punto sarà staccato dal tuo DbContext. Quando lo aggiungi al tuo modello, Entity Framework penserà che tu abbia un nuovo oggetto.

Poiché i tuoi ID sono configurati come DatabaseGenerationOptions.None, utilizzerà la chiave primaria fornita dall'utente. Nel tuo caso questo è il PK dell'oggetto distaccato. Pertanto, quando EF tenta di inserire questa voce, genererà l'eccezione sopra indicata perché un'entità con quella chiave è già presente.

ci sono alcuni modi per risolvere questo:

  • recuperare l'entità esistente

Questa entità verrà collegato al contesto su di recupero, che consente di utilizzare questo. Ciò significa comunque una ricerca extra: prima di averli nella casella combinata e quindi di utilizzare l'ID dall'entità nella casella combinata per recuperarli nuovamente dal database.

Esempio utilizzo:

AModel Get(AModel detachedModel) 
{ 
    using(var context = new MyContext()) 
    { 
     return context.AModels.Single(x => x.ID == detachedModel.ID); 
    } 
} 
  • Fissare il modello esistente

Questo dovrebbe solo fare Entity Framework-consapevole del fatto che l'entità esiste già nel database.

using(var context = new MyContext()) 
{ 
    context.AModels.Attach(detachedModel); 
} 

Altri modi per allegare è impostando lo stato di Invariato

context.Entry(detachedModel).State = EntityState.Unchanged; 

o modificati (nel caso in cui anche è stata modificata valori)

context.Entry(detachedModel).State = EntityState.Modified; 
+0

Grazie, l'ho risolto con State Unchanged e funziona come volevo. – xfrog