c# - Threading and SqlFileStream. The process cannot access the file specified because it has been opened in another transaction -


i extracting content of files in sql file table. following code works if not use parallel.

i getting following exception, when reading sql file stream simultaneously (parallel).

the process cannot access file specified because has been opened in transaction.

tl;dr:

when reading file filetable (using get_filestream_transaction_context) in parallel.foreach above exception.

sample code try out:

https://gist.github.com/nerdpad/6d9b399f2f5f5e5c6519

longer version:

fetch attachments, , extract content:

var documents = new list<extractedcontent>(); using (var ts = new transactionscope(transactionscopeasyncflowoption.enabled)) {     var attachments = await dao.getattachmentsasync();      // extract content simultaneously     // documents = attachments.todbdocuments().tolist(); // works     parallel.foreach(attachments, => documents.add(a.todbdocument())); // doesn't      ts.complete(); } 

dao read file table:

public async task<ienumerable<searchattachment>> getattachmentsasync() {     try     {         var commandstr = "....";          ienumerable<searchattachment> attachments = null;         using (var connection = new sqlconnection(this.databasecontext.database.connection.connectionstring))         using (var command = new sqlcommand(commandstr, connection))         {             connection.open();              using (var reader = await command.executereaderasync())             {                 attachments = reader.tosearchattachments().tolist();             }         }          return attachments;     }     catch (system.exception)     {         throw;     } } 

create objects each file: object contains reference get_filestream_transaction_context

public static ienumerable<searchattachment> tosearchattachments(this sqldatareader reader) {     if (!reader.hasrows)     {         yield break;     }      // convert each row searchattachment     while (reader.read())     {         yield return new searchattachment         {             ...             ...             uncpath = reader.to<string>(constants.uncpath),             contentstream = reader.to<byte[]>(constants.stream) // get_filestream_transaction_context()              ...             ...         };     } } 

read file using sqlfilestream: exception thrown here

public static extractedcontent todbdocument(this searchattachment attachment) {     // read file     // exception thrown here     using (var stream = new sqlfilestream(attachment.uncpath, attachment.contentstream, fileaccess.read, fileoptions.sequentialscan, 4096))     {         ...         // extract content file     }      .... } 

update 1:

according this article seems isolation level issue. has ever faced similar issue?

the transaction not flow in parallel.foreach, must manually bring transaction in.

//switched thread safe collection. var documents = new concurrentqueue<extractedcontent>(); using (var ts = new transactionscope(transactionscopeasyncflowoption.enabled)) {     var attachments = await dao.getattachmentsasync();     //grab reference current transaction.     var transaction = transaction.current;     parallel.foreach(attachments, =>     {         //spawn dependant clone of transaction         using (var depts = transaction.dependentclone(dependentcloneoption.rollbackifnotcomplete))         {             documents.enqueue(a.todbdocument());             depts.complete();         }     });      ts.complete(); } 

i switched list<extractedcontent> concurrentqueue<extractedcontent> because not allowed call .add( on list multiple threads @ same time.


Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -