18

I use a pattern that looks something like this often. I'm wondering if this is alright or if there is a best practice that I am not applying here.

Specifically I'm wondering; in the case that an exception is thrown is the code that I have in the finally block enough to ensure that the connection is closed appropriately?

public class SomeDataClass : IDisposable
{
    private SqlConnection _conn;

    //constructors and methods

    private DoSomethingWithTheSqlConnection()
    {
        //some code excluded for brevity

        try
        {
            using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection))
            {
                _SqlConnection.Open();
                countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
        }
        finally
        {
            //is this the best way?
            if (_SqlConnection.State == ConnectionState.Closed)
                _SqlConnection.Close();
        }

        //some code excluded for brevity
    }

    public Dispose()
    {
        _conn.Dispose();
    }
}
Eric Schoonover
  • 47,184
  • 49
  • 157
  • 202
  • 1
    Uh... why are you checking that the connection is already closed before closing it? And why use a class member to store the connection, if you're gonna close it in the only method using it? – Shog9 Sep 26 '08 at 18:46
  • 1
    spoon16 included the phrase "//some code excluded for brevity". From this, I infer that this isn't the only method using it. – Jeffrey L Whitledge Sep 26 '08 at 18:52
  • correct, this is absolutely the simplest example I could think of. I think that because of connection pooling I don't need to try to store a SqlConnection object outside the scope of each method. So just going to use USING as other recommended. – Eric Schoonover Sep 26 '08 at 20:19
  • Regarding the 'Finally' section, (Althought it has already been pointed out that it isn't necessary at all) you need to be checking if the object is null or not. You can't call .close on a null object – Andrew Harry Feb 06 '09 at 02:38

9 Answers9

46

Wrap your database handling code inside a "using"

using (SqlConnection conn = new SqlConnection (...))
{
    // Whatever happens in here, the connection is 
    // disposed of (closed) at the end.
}
Sklivvz
  • 30,601
  • 24
  • 116
  • 172
  • Also note that unless you specifically turned it off in the connection string, .NET pools connections by default so you don't need to try to hang on to the connection to reuse it. – Adam Hughes Sep 26 '08 at 19:05
  • Are the connection and cmd objects still closed inside the using block even if an exception is explicitly thrown inside the block? – Robertcode May 24 '18 at 20:22
8

The .Net Framework mantains a connection pool for a reason. Trust it! :) You don't have to write so much code just to connect to the database and release the connection.

You can just use the 'using' statement and rest assured that 'IDBConnection.Release()' will close the connection for you.

Highly elaborate 'solutions' tend to result in buggy code. Simple is better.

Joel Anair
  • 13,832
  • 3
  • 31
  • 36
Cyber Oliveira
  • 8,178
  • 4
  • 28
  • 18
6

MSDN Docs make this pretty clear...

  • The Close method rolls back any pending transactions. It then releases the connection to the connection pool, or closes the connection if connection pooling is disabled.

You probably haven't (and don't want to) disable connection pooling, so the pool ultimately manages the state of the connection after you call "Close". This could be important as you may be confused looking from the database server side at all the open connections.


  • An application can call Close more than one time. No exception is generated.

So why bother testing for Closed? Just call Close().


  • Close and Dispose are functionally equivalent.

This is why a using block results in a closed connection. using calls Dispose for you.


  • Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class.

Important safety tip. Thanks, Egon.

Amy B
  • 108,202
  • 21
  • 135
  • 185
2

I'm guessing that by _SqlConnection.State == ConnectionState.Closed you meant !=

This will certainly work. I think it is more customary to contain the connection object itself inside a using statement, but what you have is good if you want to reuse the same connection object for some reason.

One thing that you should definitely change, though, is the Dispose() method. You should not reference the connection object in dispose, because it may have already been finalized at that point. You should follow the recommended Dispose pattern instead.

Yousha Aleayoub
  • 4,532
  • 4
  • 53
  • 64
Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
1

Since you're using IDisposables anyway. You can use the 'using' keyword, which is basically equivalent to calling dispose in a finally block, but it looks better.

Aaron Maenpaa
  • 119,832
  • 11
  • 95
  • 108
1

Put the connection close code inside a "Finally" block like you show. Finally blocks are executed before the exception is thrown. Using a "using" block works just as well, but I find the explicit "Finally" method more clear.

Using statements are old hat to many developers, but younger developers might not know that off hand.

Ed Schwehm
  • 2,163
  • 4
  • 32
  • 55
  • "using" statements are very clear to anyone who is familiar with C#. I'm using Java professionally at the moment, and the extra baggage of try/finally compared with "using" is a real chore. The "using" statement is the idiomatic means of resource handling in C#. – Jon Skeet Sep 26 '08 at 19:21
  • Fair enough, but I find that even when I know what something like "using" does, actually seeing the code helps me visualize the action. Plus I'm not the only one viewing my code. – Ed Schwehm Sep 26 '08 at 20:16
1

See this question for the answer:

Close and Dispose - which to call?

If your connection lifetime is a single method call, use the using feature of the language to ensure the proper clean-up of the connection. While a try/finally block is functionally the same, it requires more code and IMO is less readable. There is no need to check the state of the connection, you can call Dispose regardless and it will handle cleaning-up the connection.

If your connection lifetime corresponds to the lifetime of a containing class, then implement IDisposable and clean-up the connection in Dispose.

Community
  • 1
  • 1
Brannon
  • 25,687
  • 5
  • 39
  • 44
0

no need for a try..finally around a "using", the using IS a try..finally

BlackTigerX
  • 6,006
  • 7
  • 38
  • 48
-4

Might I suggest this:


    class SqlOpener : IDisposable
    {
        SqlConnection _connection;

        public SqlOpener(SqlConnection connection)
        {
            _connection = connection;
            _connection.Open();

        }

        void IDisposable.Dispose()
        {
            _connection.Close();
        }
    }

    public class SomeDataClass : IDisposable
    {
        private SqlConnection _conn;

        //constructors and methods

        private void DoSomethingWithTheSqlConnection()
        {
            //some code excluded for brevity
            using (SqlCommand cmd = new SqlCommand("some sql query", _conn))
            using(new SqlOpener(_conn))
            {
                int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
            }
            //some code excluded for brevity
        }

        public void Dispose()
        {
            _conn.Dispose();
        }
    }

Hope that helps :)

Torbjörn Gyllebring
  • 17,928
  • 2
  • 29
  • 22
  • -1: doesn't work! The SqlCommand is still holding a null reference. Please don't fix it - just stick with the standard solution above – Joe Sep 26 '08 at 21:40
  • Err, really I have no problem what so ever running this assuming that the code *around* it actually creates a connection. See, if "_conn" isn't properly initialized ofcourse it won't work. – Torbjörn Gyllebring Sep 27 '08 at 08:08