Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use System.Transactions.TransactionScope with SqlBulkCopy?

Very simple question: is it possible to use System.Transactions.TransactionScope together with SqlBulkCopy? The documentation Transaction and Bulk Copy Operations doesn't mention anything (at least as of .NET 4.0) and my testing indicates it does not automatically enlist with TransactionScope.

like image 640
jason Avatar asked Sep 06 '11 00:09

jason


People also ask

Does SqlBulkCopy use transaction?

By default, a bulk copy operation is its own transaction. When you want to perform a dedicated bulk copy operation, create a new instance of SqlBulkCopy with a connection string, or use an existing SqlConnection object without an active transaction.

What is TransactionScope in C#?

The TransactionScope class provides a simple way to mark a block of code as participating in a transaction, without requiring you to interact with the transaction itself. A transaction scope can select and manage the ambient transaction automatically.

What is SqlBulkCopy in VB net?

SqlBulkCopy lets you bulk load a SQL Server table with data from another source. This means that it copies (in bulk) data from another source into an SQL database table.


1 Answers

SqlBulkCopy never enlists into a transaction. SqlCommand also does not do that. Common misconception. The enlistment is performed at the time SqlConnection.Open is called. After that, anything that runs on that connection is part of the transaction implicitly. In fact it is no longer allowed to pass an explicit transaction.

If you want SqlBulkCopy to take part in a System.Transactions.Transaction using TransactionScope the transaction must be set at the time you open the connection.

It is very easy to do:

using (var tran = new TransactionScope(...)) using (var conn = new SqlConnection(connStr)) {   conn.Open(); //This enlists.    using (var sqlBulkCopy = new SqlBulkCopy(conn)) {     sqlBulkCopy.WriteToServer(...);   }    tran.Complete(); //Commit. } 

This code is all you need. Possible mistakes:

  1. The transaction must be opened early enough.
  2. Do not use the SqlTransaction parameter of SqlBulkCopy. Pass null.
  3. Do not use SqlBulkCopyOptions.UseInternalTransaction.
  4. Do not add exception handling unless you want to actually do something. Rollback is automatic if there is no commit.
  5. Use the using statement for clean code and deterministic cleanup. Do not manually close or dispose any of these objects unless you have to. This would be redundant.

You can use any batch size you like and all batches will be part of the transaction. Therefore, batching has limited value (in particular the transaction log cannot be truncated early). Try no batching at all first.

like image 163
usr Avatar answered Sep 17 '22 12:09

usr