Meep
Meep

Reputation: 103

Adding Transaction Scope to Parallel.Foreach

I have a loop inserting records into a database (Firebird):

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
    taskList.Add(Task.Factory.StartNew(() =>
    {       
        Parallel.ForEach(objectList, c =>
        {
            DoInsert(c, id);
        });
    }));

    scope.Complete()
}

I would like the ability to rollback these inserts as a batch if the insert fails. However as I'm performing the insert within a Parallel.Foreach loop, the transaction scope isn't visible. I'm assuming that's because the loop is operating in a different thread. If I do this as a serial insert using TransactionScope, everything works.

I've tried to use a DependentTransaction but I can't seem to get the context to the DoInsert function. The DoInsert simply opens a connection and writes the contents of C to the database.

Any ideas?

Thanks,

Upvotes: 6

Views: 4510

Answers (1)

Kris Vandermotten
Kris Vandermotten

Reputation: 10201

You cannot do this using a single TransactionScope, for the reason you mentioned: TransactionScope relies on threadlocal storage, and you are in a multithreaded environment.

But more importantly, for this to work, every worker thread would need to open a connection, enlist it in a distributed transaction, do the insert, and close the connection.

If these are simple inserts, I'd be very surprised that creating all these connections would give you any performance benefit. In fact, I believe this program would be a lot faster if you did it on a single thread, and on a single connection. Obviously, that implies that the connection is opened (and closed) once, and passed into the DoInsert method as a parameter.

Even better, you might want to look at bulk insert.

Upvotes: 7

Related Questions