C'è un sacco di informazioni e risposte su qui e altrove su come velocizzare gli inserimenti di massa con EF.
Tuttavia, inserisco solo circa 10.000 record e la parte lenta della creazione delle entità.
Innanzitutto, salvi i dati esterni in un datatable, quindi eseguo il ciclo e, per ogni riga, creo una nuova entity
, aggiungi le entità child nel ciclo (proveniente da un paio di altri datatables) e una volta terminato il ciclo chiama db.SaveChanges()
.
Nella mia profilazione iniziale, db.SaveChanges()
è lento, ma nulla in confronto al ciclo di creazione di tutti gli oggetti in primo luogo - come List<entity> entities
separata di List<entity> entities
o direttamente nel contesto.
È normale? Come tutti i problemi con l'inserimento bulk posso vedere, la maggior parte sembra essere correlata al commit finale del database.
Modifica per aggiungere del codice Si prega di scusare il psudo-codice
DataTable ref1 = ConvertCSVtoDataTable(csv, firstRowsToDelete: 15); // Return's a Datatable from a CSV
foreach(string file in ListOfFilesToProcess)
{
DataTable tbl = loadExcelFiles(file);
foreach(DataRow dr in tbl.Rows)
{
Entity newEntity = new Entity();
Entity.property1 = dr["Property1"].ToString();
... // Keep mapping properties to elements in the datatable
Entity.Child.Add(new ChildEntity() { prop1 = ref1["ChildProp1"].ToString() });
// Add the newly created entity to the context
db.Entity.Add(newEntity);
}
}
// Save the context
db.SaveChanges();
Quindi, al punto di salvare il contesto, ci sono alcune migliaia di oggetti newEntity
e i relativi oggetti di navigation
figlio.
Iterare sul datatable e creare tutti questi oggetti è la parte più lenta!
Inoltre, db.Configuration.AutoDetectChangesEnabled = false;
è già stato impostato.
La parte lenta nella sezione "Creare tutti gli oggetti" è il Rileva cambiamenti.
Dovresti sempre usare AddRange su Aggiungi
Questo codice dovrebbe risolvere la parte lenta durante la creazione di oggetti:
DataTable ref1 = ConvertCSVtoDataTable(csv, firstRowsToDelete: 15); // Return's a Datatable from a CSV
List<Entity> list = new List<Entity>();
foreach(string file in ListOfFilesToProcess)
{
DataTable tbl = loadExcelFiles(file);
foreach(DataRow dr in tbl.Rows)
{
Entity newEntity = new Entity();
Entity.property1 = dr["Property1"].ToString();
... // Keep mapping properties to elements in the datatable
Entity.Child.Add(new ChildEntity() { prop1 = ref1["ChildProp1"].ToString() });
list.Add(newEntity);
}
}
// Add all newly created entities to the context
db.Entity.AddRange(list);
// Save the context
db.SaveChanges();
Se dopo questa correzione hai ancora qualche problema con le prestazioni (dal database questa volta), dovresti provare una libreria di terze parti BulkSaveChanges / Bulk Insert.
Ecco un articolo su queste librerie: Entity Framework - Bulk Insert Library Reviews & Comparisons .
Disclaimer : sono il proprietario del progetto Entity Framework Extensions
Basta usare un inserto di massa. Anche se superi le prestazioni ridicolmente cattive di EF, devi comunque fare i conti con il database che non ama i singoli inserti.