Modo efficiente per inserire / aggiornare in blocco con Entity Framework

Ho una lista di quadro e voglio inserirle in un database. Se l’entity framework esiste già nel database così com’è, deve essere saltata. Se è nel database ma con valori diversi, deve essere aggiornato.

C’è un modo per fare questo diverso da fare una chiamata db per elemento?

Il mio piano è provare un inserto, se viene lanciata un’eccezione di vincolo univoca sulla chiave, quindi fare un aggiornamento.

Basta non usare Entity Framework in questo caso . Basta usare una procedura memorizzata (come dipendere dalla versione / approccio che usi con EF, potresti dover estendere il tuo DbContext o aggiungere una mapping dal modello quadro).

Se si utilizza SQL Server, quindi nella procedura di archiviazione, utilizzare il comando MERGE che fa esattamente ciò di cui si ha bisogno: inserire se non esiste o aggiornare se lo fa. Tutto in una singola query SQL efficiente.

EF non è adatto per inserti BULK. Per 1000 di record va bene, ma i numeri grandi (100k più) sono lenti.

Se stai pensando di usare EF.

  • prova il metodo AddOrUpdate, (invece di insert / Update)
  • Disabilita il tracciamento,
  • commettere ogni 1000 record o meno.

per esempio

 Context.Set().AddOrUpdate(poco); //... Context.Configuration.AutoDetectChangesEnabled = //.. Context.SaveChanges(); 

Se copi dati non correlati puoi provare queste tabelle in parallelo (doh)

Ho fatto un’estensione per questo https://efbulkinsert.codeplex.com/

ed è davvero semplice da usare

 using(var context = new MyDbContext()) { context.BulkInsert(hugeCollectionOfEntities); } 
  1. Creare una tabella temporanea: SqlCommand (string.Format (“SELECT TOP 0 * INTO {0} FROM {1} …

  2. Inserimento di dati di massa in esso – Entity Framework Extended di cui sopra avrebbe bisogno di essere ottimizzato per supportare il nome della tabella temporanea, ma altrimenti è sulla giusta strada – o eseguire un po ‘di codice e usare SqlBulkCopy.

  3. Costruisci una dichiarazione MERGE.

Se si estrae un elenco di proprietà, è ansible effettuare (2) e (3) generici. Posso leggere e unire 150.000 righe in circa 20 secondi.