views:

44

answers:

3

Suppose we have a DAL method

public void BuyProduct(int productId, int quantity, int buyerId);

Within that method we need to call 2 stored procedures:

  1. EXEC tblOrders_CreateNewOrder
  2. EXEC tblProducts_RecalculateStock

Is it a good practice to create 2 SqlCommands - one per stored procedure and to use a single SqlConnection to execute those commands?

OR

Is it better to create a separate SqlConnection for each SqlCommand?

So basically I am asking: is it a good practice to reuse a single SqlConnection for multiple (2-4) SqlCommands within a single DAL method (obviously reusing SqlConnection across the entire DAL would be dumb)?

PS - please do not ask me why can't I just combine the 2 stored procedures into 1. My answer is - separation of concerns.

+1  A: 

By default .NET creates a pooled SqlConnection. So creating new connections (provided all of them use the same connection string) does not cause an overhead until the pool is completely exhausted.

Kangkan
True that, however SqlConnection.Open() is an expensive operation and I prefer to have to call it once rather than 2-4 times within a single DAL method.
niaher
You can of course use it. Only point is that one should not hold idle an object too long. If you are calling the two stored procs in succession, you of course can use the same SqlConnection.
Kangkan
+4  A: 

The real problem is not the connection, but the transactions. When a logical operation involves multiple DAL physical operations, usually they have to be part of a transcation. Unless corectness is optional... If a transaction spans multiple connections then it has to be elevated to a distributed transaction, with disastrous perofrmance results. So when designing a DAL, always thrive to affinitize a transaction to a connection. This ripples through the DAL API design, as usually the result is that the conneciton and transaction objects have to be explictly handed out to the DAL methods, either as individual parameters or as a 'context' object that aggregates them.

Remus Rusanu
Thanks Remus. I take that it is OK to share SqlConnection within DAL method as long as the transaction's correctness is optional (which is exactly my case).
niaher
+2  A: 

Yes, it's a good practice to reuse a single SqlConnection for multiple SqlCommands (within one method). As I understood in your case you also need to use SqlTransaction like this:

public void SomeDALMethod(string connectionString)
{
    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();

        var transaction = connection.BeginTransaction();

        var command1 = new SqlCommand("tblOrders_CreateNewOrder", connection, transaction)
                        {
                            CommandType = CommandType.StoredProcedure
                        };
        var command2 = new SqlCommand("tblProducts_RecalculateStock", connection, transaction)
                        {
                            CommandType = CommandType.StoredProcedure
                        };

        try
        {
            command1.ExecuteNonQuery();
            command2.ExecuteNonQuery();
            transaction.Commit();
        }
        catch (Exception ex)
        {
            // Commit failed
            try
            {
                transaction.Rollback();
            }
            catch (Exception ex2)
            {
                // Rollback failed
            }
        }           
    }
}

It allows you to rollback execution of the first stored procedure in case of the second sp failed.

bniwredyc
Thanks for the code example. Btw why do you use var and not the actual type?
niaher
@niaher: it's shorter. Compare `Dictionary<string, string> d = new Dictionary<string, string>()` and `var d = new Dictionary<string, string>()`.
bniwredyc