- I have SQL Server 2000, it doesn't support MultipleActiveResults.
- I have to do multiple inserts, and it's done with one connection per insertion.
- I want to begin a transaction before all insertions and finish it after all insertions.
- How do I do it?

- 422,506
- 82
- 585
- 676

- 88,211
- 155
- 421
- 625
-
2Can you post some of your code, I get that 2k doesn't support MultipleActiveResults, but that only matters for simultaneous batches on a connection, you can certainly have multiple executes with a command object on a given connection. – cmsjr Mar 06 '09 at 20:06
-
Jader, I agree with Cmsjr, sinple case tested with SQL 8.00.194. Your code may be specific, but then we need more info. – Maksym Gontar Mar 07 '09 at 07:56
4 Answers
You didn't specify if you're using .NET 2.0, but I'll make that assumption. C# 3.0 sample code is listed below:
using (var tx = new TransactionScope()) {
// Execute multiple DB statements inside here
ts.Complete();
}
If any of the DB statements fail, the ts.complete will never be reached and the transaction will be rolled back automatically at the end of the using statement. However, one caveat to this approach is that you'll end up leveraging the DTC if you use multiple connections, which means slower performance.
Edited to change SqlTransaction to TransactionScope
An example of forcing a single SQL connection to avoid using the DTC:
using (var tx = new TransactionScope())
using (var db = new SqlConnection(connString)) {
// Command 1
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 2
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
// Command 3
using (var cmd = db.CreateCommand()) {
cmd.CommandText = "select...";
using (var reader = cmd.ExecuteReader()) {
// Process results or store them somewhere for later
}
}
tx.Complete();
}

- 6,815
- 5
- 41
- 64

- 27,596
- 25
- 124
- 225
-
any alternative to multiple connections in Sql Server 2000? I know that Sql Server 2005 supports M.A.R.S, but 2000 don't. – Jader Dias Mar 06 '09 at 18:23
-
There is no public constructor for SqlTransaction. The only way I know to create an instance is to use SqlConnection.BeginTransaction method, which is not static. – Jader Dias Mar 06 '09 at 18:27
-
-
Also, you can execute multiple commands using the same connection and store the results. I'll update post again... – Chris Mar 06 '09 at 18:57
Transactions are created on a connection and have no scope beyond the connection they are created on so you can't do what you are asking. Refactor so that you can execute the inserts sequentially on a connection rather than simultaneously or implement a different mechanism to achieve rollback (e.g. a table of inserted keys that can be used as a look up to delete inserted records if an error is encountered later in the process)

- 56,771
- 11
- 70
- 62
What is the reason you don't use one connection and multiple commands (actually one command recreated in loop)? Maybe this solution will work for you:
public static void CommandExecNonQuery(SqlCommand cmd, string query, SqlParameter[] prms)
{
cmd.CommandText = query;
cmd.Parameters.AddRange(prms);
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
static void Main(string[] args)
{
string insertQuery =
@"INSERT TESTTABLE (COLUMN1, COLUMN2) " +
"VALUES(@ParamCol1, @ParamCol2)";
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = connection.CreateCommand())
{
SqlTransaction transaction = null;
try
{
// BeginTransaction() Requires Open Connection
connection.Open();
transaction = connection.BeginTransaction();
// Assign Transaction to Command
command.Transaction = transaction;
for (int i = 0; i < 100; i++)
CommandExecNonQuery(command, insertQuery,
new SqlParameter[] {
new SqlParameter("@ParamCol1", i),
new SqlParameter("@ParamCol2", i.ToString()) });
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
finally
{
connection.Close();
}
}
}
}
Also see
Sql Server Transactions - ADO.NET 2.0 - Commit and Rollback - Using Statement - IDisposable

- 375
- 1
- 5
- 21

- 22,765
- 10
- 78
- 114
-
-
Would be better to dispose the SqlTransaction with a using statement rather than the explicit catch/finally. Disposing a transaction rolls it back if it hasn't been committed. – Joe Mar 06 '09 at 21:03
-
-
Joe, you right, SqlTransaction may be used the way you described. Still I prefer exception handling, it's more agile. – Maksym Gontar Mar 07 '09 at 07:53
I don't think a transaction can span multiple connections.
What's the reasoning for doing the multiple inserts in separate connections? I would think you'd want them in a single connection normally.

- 9,882
- 9
- 34
- 41
-
Sql Server 2000 doesn't supports MultipleActiveResultSets. So I had to create a connection for each insertion. – Jader Dias Mar 06 '09 at 18:46
-
1@JaderDias MARS is not required for reusing a single `IDbConnection` with multiple `IDbCommand`s. In fact, if you’re using SqlClient, ADO’s connection pool will effectively cause you to reuse the same connection to the database even if your code appears to close and reopen the connection. – binki Jan 22 '14 at 15:23