Entity Framework Code Primo metodo AddOrUpdate insert Valori duplicati

Ho un’entity framework semplice:

public class Hall { [Key] public int Id {get; set;} public string Name [get; set;} } 

Quindi nel metodo Seed uso AddOrUpdate per popolare la tabella:

 var hall1 = new Hall { Name = "French" }; var hall2 = new Hall { Name = "German" }; var hall3 = new Hall { Name = "Japanese" }; context.Halls.AddOrUpdate( h => h.Name, hall1, hall2, hall3 ); 

Quindi eseguo nella console di gestione pacchetti:

 Add-Migration Current Update-Database 

Va tutto bene: ho tre file nella tabella “Hall”. Ma se Update-Database nuovamente il Update-Database console di gestione pacchetti, ho già cinque righe:

 Id Name 1 French 2 Japaneese 3 German 4 French 5 Japanese 

Perché? Penso che dovrebbe essere di nuovo tre righe, non cinque. Ho provato a usare la proprietà Id posto di Name ma non fa la differenza.

AGGIORNARE:

Questo codice produce lo stesso risultato:

 var hall1 = new Hall { Id = 1, Name = "French" }; var hall2 = new Hall { Id = 2, Name = "German" }; var hall3 = new Hall { Id = 3, Name = "Japanese" }; context.Halls.AddOrUpdate( h => h.Id, hall1); context.Halls.AddOrUpdate( h => h.Id, hall2); context.Halls.AddOrUpdate( h => h.Id, hall3); 

Inoltre ho l’ultimo EntityFramework installato tramite nuget.

Ok stavo sbattendo la faccia dalla tastiera per un’ora con questo. Se il campo ID della tua tabella è un campo Identity framework, non funzionerà, quindi utilizza uno diverso per identifierExpression. Ho usato la proprietà Name e rimosso anche il campo Id dal new Hall {...} inizializzatore new Hall {...} .

Questa modifica al codice OP ha funzionato per me quindi spero che aiuti qualcuno:

 protected override void Seed(HallContext context) { context.Halls.AddOrUpdate( h => h.Name, // Use Name (or some other unique field) instead of Id new Hall { Name = "Hall 1" }, new Hall { Name = "Hall 2" }); context.SaveChanges(); } 

Questo codice funziona:

 public Configuration() { AutomaticMigrationsEnabled = true; } protected override void Seed(HallContext context) { context.Halls.AddOrUpdate( h => h.Id, new Hall { Id = 1, Name = "Hall 1" }, new Hall { Id = 2, Name = "Hall 2" }); context.SaveChanges(); } 

So che questa è una vecchia domanda, ma la risposta giusta è che se si imposta l’id # da soli e si desidera utilizzare AddOrUpdate, è necessario indicare a EF / SQL che non si desidera che generi il numero ID.

 modelBuilder.Entity().Property(p => p.Id) .HasDatabaseGeneratedOption(System.ComponentModel .DataAnnotations.Schema.DatabaseGeneratedOption.None); 

Il lato negativo di questo è che quando si inserisce un nuovo elemento è necessario impostarlo come ID, quindi se questo viene fatto dynamicmente in fase di esecuzione (anziché da dati seme), allora sarà necessario calcolare il prossimo Id. Context.MyClasses.Max(c=>c.Id) + 1 funziona bene.

Ciò può anche essere causato se si imposta lo stato entity framework in modo errato. Continuavo a ricevere il seguente errore quando eseguivo update-database … “La sequenza contiene più di un elemento corrispondente.”

Ad esempio, avevo creato due righe duplicate su ogni comando update-database (che ovviamente non dovrebbe accadere quando si semina dati), e quindi il prossimo comando update-database non funzionerebbe affatto poiché ha trovato più di una corrispondenza (da qui l’errore di sequenza che dice che ho più di una riga corrispondente). Questo perché avevo sovrascritto SaveChanges nel mio file di contesto con una chiamata di metodo a ApplyStateChanges …

 public override int SaveChanges() { this.ApplyStateChanges(); return base.SaveChanges(); } 

Stavo usando ApplyStateChanges per garantire che quando si aggiungono i grafici degli oggetti, Entity Framework sa esplicitamente se l’object si trova in uno stato aggiunto o modificato. L’intera spiegazione su come sto usando ApplyStateChanges può essere trovata qui .

E questo funziona alla grande (ma l’avvertenza !!) … se si semina anche il database usando le migrazioni CodeFirst, allora il metodo sopra causerà il caos per la chiamata AddOrUpdate () all’interno del metodo Seed. Quindi, prima di ogni altra cosa, è sufficiente controllare il file DBContext e assicurarsi di non sovrascrivere SaveChanges nel modo precedente, altrimenti si otterranno dati duplicati che eseguono il comando update-database una seconda volta e quindi non funzioneranno affatto. terza volta poiché c’è più di una riga per ogni object corrispondente.

Quando si tratta di esso, non è necessario configurare l’ID in AddOrUpdate () … che vanifica l’intero scopo della semina database semplice e iniziale. Funziona bene con qualcosa come:

 context.Students.AddOrUpdate( p => p.StudentName, new Student { StudentName = "Bill Peters" }, new Student { StudentName = "Jandra Nancy" }, new Student { StudentName = "Rowan Miller" }, new Student { StudentName = "James O'Dalley" }, 

solo PERCHÉ non escludo il metodo SaveChanges nel mio file di contesto con una chiamata a ApplyStateChanges. Spero che questo ti aiuti.

Questo ha funzionato per me

  1. Elimina tutte le righe nella tabella.
  2. Reimposta l’id quadro incrementale su 0. DBCC CHECKIDENT (yourtablename, RESEED, 0) (Le chiavi primarie specificate in Seed() devono corrispondere a quelle nella tabella del database in modo che non vengano duplicate).
  3. Specificare le chiavi primarie nel metodo “seme”.
  4. Esegui il metodo Seed() più volte e verifichi se sono duplicati.

Ho trovato che AddOrUpdate funziona bene con campi che non sono ID. Se questo funziona per te: context.Halls.AddOrUpdate(h => h.Name, hall1, hall2, hall3)

Puoi utilizzare i nomi di Hall come “French_test_abc_100”, “German_test_abc_100” ecc.

Questo impedisce ai dati del test codificati di rovinare le cose quando testate la vostra app.

Se l’id dell’object (hall) è 0, è un inserimento. Penso che sia necessario ricontrollare il campo ID dei tuoi oggetti Hall

Il tuo campo ID è un campo Id quadro? Mi stavo imbattendo in questo stesso problema. Quando ho rimosso lo stato Identity dal mio campo ID e ho impostato gli ID nel database, questo ha risolto il problema.

Questo ha funzionato per me, dal momento che queste erano tabelle di ricerca e non avrebbero dovuto essere campi di identity framework, comunque.

Penso che sia probabile che sia necessario annullare le migrazioni di database esistenti (ad esempio, avviare il database da zero) con qualcosa come “Update-Database TargetMigration: 0” seguito da “Update-Database”.

Così com’è, non stai perdendo la tabella oi valori esistenti, devi solo aggiungere / aggiornare quei valori. Questo deve accadere per ottenere il risultato desiderato.

Ecco un buon riferimento per le migrazioni EF: http://elegantcode.com/2012/04/12/entity-framework-migrations-tips/

Ho usato il campo ID come Identity / Key e ho aggiunto attributi per non assegnare Ids dal server. Questo ha risolto il problema per me.

 public class Hall { [Key] [Required] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id {get; set;} public string Name [get; set;} } 

Proprio alla risposta di Ciaren, il codice sottostante di reimpostazione del contesto su ModelCreating mi ha aiutato a risolvere problemi simili. Assicurarsi di modificare “ApplicationContext” nel nome DbContext.

 public class ApplicationContext : DbContext, IDbContext { public ApplicationContext() : base("ApplicationContext") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove(); Database.SetInitializer(null); base.OnModelCreating(modelBuilder); } } 

Avresti anche potuto farlo:

  context.Halls.AddOrUpdate(new Hall[]{hall1,hall2, hall3}); 

Ho scoperto che, per far funzionare tutto questo, la posizione dell’id quadro dovrebbe essere 0 quando il seme viene eseguito per la prima volta. Puoi resettarlo usando:

 DBCC CHECKIDENT (tableName, RESEED, 0)