SqlBulkCopy insère quand à l'intérieur d'une transaction empêche toute autre écriture sur une table

asp.net c# sql sqlbulkcopy sql-server

Question

Dans mon application Web, les utilisateurs peuvent insérer plusieurs données à la fois. Pour améliorer les performances, j'utilise la classe SqlBulkCopy. Il s'exécute plusieurs fois pour une seule opération en l'insérant dans deux tables différentes. Si l'utilisateur annule l'opération ou si elle échoue, il faut que les données soient restaurées afin d'envelopper tout dans une transaction à l'aide du cliché de niveau d'isolation.

Je pensais que l’utilisation de l’isolation de capture instantanée permettrait à d’autres utilisateurs d’écrire / lire simultanément sur les tables. Cependant, lorsqu'un téléchargement de données est en cours, il bloque toutes les autres écritures dans la table jusqu'à ce que la transaction parente complète soit terminée.

Voici un code simplifié qui montre le problème. J'exclus beaucoup de fonctions mais l'idée reste la même. Je parcourt un certain nombre de collections en mémoire, les copie en bloc dans une table, les retire en arrière et les copie en bloc dans une autre table.

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();
 }

Ainsi, si un utilisateur est actuellement dans cette transaction, même si elle est en train d'être annulée, toutes les autres transactions d'écriture dans la table seront bloquées, de sorte que les autres utilisateurs effectuant la même fonction ou tentant d'écrire dans la table seront bloqués.

Est-ce le comportement attendu et y a-t-il un moyen de contourner cela?

modifier

En regardant les verrous appliqués en SQL, cela semble être dû au fait que la classe bulkcopy a pour conséquence qu'un verrou exclusif (X) est défini sur l'objet table, comme si vous deviez les insérer un par un, seul un verrou d'intention est appliqué. sur la table (IX). Vous ne savez toujours pas s’il existe un moyen de contourner ce problème, mais j’assume que cela est dû à une escalade de verrous.

La modification du verrouillage de page Autoriser sur les index des tables et la taille des lots de copies en bloc ont permis de supprimer le verrouillage complet de certains de mes tests, mais ils sont capricieux.

Réponse populaire

IsolationLevel fait uniquement référence à des lectures et non à des écritures. Si l'un de vos clients écrit des données, l'autre client doit pouvoir lire les données telles qu'elles étaient avant le début de la transaction. Toutefois, il ne pourra pas écrire en même temps.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi