SqlBulkCopy se inserta cuando dentro de una transacción evita cualquier otra escritura en una tabla

asp.net c# sql sqlbulkcopy sql-server

Pregunta

En mi aplicación web, los usuarios pueden insertar muchos datos a la vez, para mejorar el rendimiento estoy usando la clase SqlBulkCopy. Se ejecuta varias veces para una sola operación insertándose en dos tablas diferentes. Si el usuario cancela la operación o falla, entonces necesito que los datos se restituyan, así que lo envuelvo todo en una transacción utilizando el nivel de aislamiento Instantánea.

Según mi entendimiento, el uso del aislamiento de instantáneas permitiría a otros usuarios escribir / leer en las tablas simultáneamente. Sin embargo, mientras se produce una carga de datos, bloqueará cualquier otra escritura en la tabla hasta que se complete la transacción principal completa.

Aquí hay un código simplificado que muestra el problema. Estoy excluyendo muchas de las funciones pero la idea sigue siendo la misma. Repaso un número de recopilaciones en memoria, las coloco en una tabla, las retiro y las copia en otra tabla.

using (var transaction = myDbContext.Database.BeginTransaction(
System.Data.IsolationLevel.Snapshot))
 {
   var myCollectionOfObjects;

   while(!GetData(ref myCollectionOfObjects))  
   {     

    SqlBulkCopy bulkCopy = new SqlBulkCopy(myCon, transaction);

    //Sets the columns + rows
    SetUp(bulkCopy);

    bulkCopy.WriteToServer();
    //After the bulkcopy operation is complete
    // we retrieve the rows inserted and do another bulk copy to a different table

    var recentlyAddedRows = GetRecentlyAddedRow();

    SqlBulkCopy otherTableBulkCopy = new SqlBulkCopy(myCon, transaction);


    SetUpBulkCopyForOtherTable(otherTableBulkCopy);

    otherTableBulkCopy.WriteToServer();         
     }
    transaction.Commit();
 }

Por lo tanto, si un usuario está actualmente dentro de esta transacción, incluso si está retrocediendo, todas las demás transacciones de escritura en la tabla se bloquearán, de modo que otros usuarios que realicen la misma función o intenten escribir en la tabla serán bloqueados.

¿Es este el comportamiento esperado y hay una manera de evitar esto?

Editar

Al observar los bloqueos aplicados en SQL, parece deberse a que la clase de copia masiva da lugar a un bloqueo exclusivo (X) que se establece en el objeto de la tabla, donde como si los insertara uno a la vez, solo se aplica un bloqueo de intención Sobre la mesa (IX). Todavía no estoy seguro de si hay una forma de evitar esto, pero supongo que esto se debe a una escalada de bloqueo.

El cambio del bloqueo de página Permitir en los índices de las tablas y el cambio del tamaño de los lotes de las copias masivas han logrado evitar el bloqueo completo en algunas de mis pruebas, pero son temperamentales.

Respuesta popular

IsolationLevel solo se refiere a las lecturas y no a las escrituras. Si uno de su cliente está escribiendo datos, el otro cliente debería poder leer los datos tal como estaban antes del inicio de la transacción, sin embargo, no podrá escribir al mismo tiempo.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué