SqlBulkCopy inserisce quando all'interno di una transazione impedisce qualsiasi altra scrittura su una tabella

asp.net c# sql sqlbulkcopy sql-server

Domanda

Nella mia app web gli utenti possono inserire molti dati contemporaneamente, per migliorare le prestazioni sto usando la classe SqlBulkCopy. Funziona più volte per un'unica operazione inserendo due tabelle diverse. Se l'utente annulla l'operazione o fallisce, ho bisogno che i dati tornino indietro, quindi avvolgo tutto in una transazione utilizzando l'istantanea a livello di isolamento.

Ho capito che l'uso dell'isolamento dello snapshot avrebbe consentito agli altri utenti di scrivere / leggere contemporaneamente sulle tabelle. Tuttavia, mentre si sta verificando un caricamento di dati, bloccherà qualsiasi altra scrittura sulla tabella fino al completamento dell'intera transazione principale.

Ecco un codice semplificato che mostra il problema. Sto escludendo molte funzioni, ma l'idea rimane la stessa. Eseguo un certo numero di una raccolta in memoria, li bulkcopy su una tabella, li ritirare e copia in massa su un'altra tabella.

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

Pertanto, se un utente si trova attualmente in questa transazione, anche se si sta eseguendo il rollback, tutte le altre transazioni di scrittura nella tabella verranno bloccate, in modo che altri utenti che eseguono la stessa funzione o tenteranno di scrivere sulla tabella verranno bloccati.

È questo il comportamento previsto e c'è un modo per aggirare questo?

modificare

Osservando i blocchi applicati in SQL sembra essere dovuto alla classe bulkcopy che ha come risultato un blocco esclusivo (X) impostato sull'oggetto tabella dove, come se si inserissero uno alla volta, si applica solo un blocco intent sul tavolo (IX). Non sono ancora sicuro se c'è un modo per aggirare questo, ma presumo che questo è dovuto al blocco escalation.

La modifica del blocco della pagina Consenti sugli indici delle tabelle e la modifica delle dimensioni dei batch delle copie di massa hanno aggirato il blocco completo in alcuni dei miei test, ma sono caratteriali.

Risposta popolare

IsolationLevel si riferisce solo alle letture e non alle scritture. Se uno dei tuoi clienti sta scrivendo dati, l'altro client dovrebbe essere in grado di leggere i dati come era prima dell'inizio della transazione, tuttavia, non sarà in grado di scrivere allo stesso tempo.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow