Solución:
Para EFCore, puede usar esta biblioteca:
https://github.com/borisdj/EFCore.BulkExtensions
Y para EF 6 este:
https://github.com/TomaszMierzejowski/EntityFramework.BulkExtensions
Ambos se están extendiendo DbContext
con operaciones Bulk y tienen la misma sintaxis llamada:
context.BulkInsert(entitiesList);
context.BulkUpdate(entitiesList);
context.BulkDelete(entitiesList);
La versión EFCore tiene adicionalmente BulkInsertOrUpdate
método.
- Suponiendo que las clases en apiData son las mismas que sus entidades, debería poder usar
Attach(newAccount, originalAccount)
para actualizar una entidad existente. -
Para insertos a granel que uso
AddRange(listOfNewEntitities)
. Si tiene muchas entidades para insertar, es recomendable agruparlas. También es posible que desee desechar y recrear elDbContext
en cada lote para que no utilice demasiada memoria.var accounts = new List<Account>(); var context = new YourDbContext(); context.Configuration.AutoDetectChangesEnabled = false; foreach (var account in apiData) { accounts.Add(account); if (accounts.Count % 1000 == 0) // Play with this number to see what works best { context.Set<Account>().AddRange(accounts); accounts = new List<Account>(); context.ChangeTracker.DetectChanges(); context.SaveChanges(); context?.Dispose(); context = new YourDbContext(); } } context.Set<Account>().AddRange(accounts); context.ChangeTracker.DetectChanges(); context.SaveChanges(); context?.Dispose();
Para actualizaciones masivas, no hay nada integrado en LINQ to SQL. Sin embargo, existen bibliotecas y soluciones para abordar esto. Consulte, por ejemplo, aquí para obtener una solución utilizando árboles de expresión.
Lista frente a diccionario
Verifica en una lista cada vez si la entidad existe, lo cual es malo. En su lugar, debería crear un diccionario para mejorar el rendimiento.
var existingAccounts = _accountRepository.GetAllList().ToDictionary(x => x.AccountID);
Account existingAccount;
if(existingAccounts.TryGetValue(account.AccountId, out existingAccount))
{
// ...code....
}
Agregar frente a AddRange
Debe tener en cuenta el rendimiento de Agregar frente a AddRange cuando agrega varios registros.
- Agregar: Detección de llamadas Cambios después de agregar cada registro
- AddRange: Call DetectChanges después de agregar todos los registros
Entonces, en 10,000 entidades, el método Agregar ha tomado 875 veces más tiempo para agregar entidades en el contexto de manera simple.
Arreglarlo:
-
Crear una lista
- AÑADIR entidad a la lista
- USE AddRange con la lista
- Guardar cambios
- ¡Hecho!
En su caso, deberá crear un método InsertRange en su repositorio.
EF extendido
Tienes razón. Esta biblioteca actualiza todos los datos con el mismo valor. Eso no es lo que busca.
Descargo de responsabilidad: Soy el propietario del proyecto Entity Framework Extensions
Esta biblioteca puede adaptarse perfectamente a su empresa si desea mejorar drásticamente su rendimiento.
Puede realizar fácilmente:
- BulkSaveChanges
- BulkInsert
- Actualización masiva
- BulkDelete
- BulkMerge
Ejemplo:
public void ProcessApiData(List<Account> apiData)
{
// Insert or Update using the primary key (AccountID)
CurrentUnitOfWork.BulkMerge(apiData);
}