net c# .net sql sql-server performance

c# - net - ¿Alguna forma de SQLBulkCopy "insertar o actualizar si existe"?



max pool size web config (5)

Necesito actualizar una tabla muy grande periódicamente y SQLBulkCopy es perfecto para eso, solo que tengo un índice de 2 columnas que evita duplicados. ¿Hay alguna forma de usar SQLBulkCopy como "insertar o actualizar si existe"?

Si no, ¿cuál es la forma más eficiente de hacerlo? Una vez más, estoy hablando de una tabla con millones de registros.

Gracias



En lugar de crear una nueva tabla temporal, que por cierto consume más espacio y memoria.

Creé un disparador con INSTEAD OF INSERT y lo uso dentro de la sentencia MERGE.

Pero no olvide agregar el parámetro SqlBulkCopyOptions.Fire Triggers en SqlBulkCopy.

Estos son mis dos centavos.


No en un solo paso, pero en SQL Server 2008 , podría:

  • carga masiva en la mesa de preparación
  • aplique una declaración MERGE para actualizar / insertar en su tabla real

Lea más acerca de la declaración MERGE


Otra alternativa sería no usar una tabla temporal, sino usar un procedimiento almacenado con un parámetro de valor de tabla. Pase un datatable al sp y haga la fusión allí.


Publiqué un paquete nuget (SqlBulkTools) para resolver este problema.

Aquí hay un ejemplo de código que lograría un aumento de volumen.

var bulk = new BulkOperations(); var books = GetBooks(); using (TransactionScope trans = new TransactionScope()) { using (SqlConnection conn = new SqlConnection(ConfigurationManager .ConnectionStrings["SqlBulkToolsTest"].ConnectionString)) { bulk.Setup<Book>() .ForCollection(books) .WithTable("Books") .AddAllColumns() .BulkInsertOrUpdate() .MatchTargetOn(x => x.ISBN) .Commit(conn); } trans.Complete(); }

Para tablas muy grandes, hay opciones para agregar bloqueos de tabla y desactivar temporalmente los índices no agrupados. Vea la documentación de SqlBulkTools para más ejemplos.