2

I am the third generation to work on a system within my organization and of course there are differences in programming styles. I was wondering what the correct way of connecting to a database is as there are two different styles being used within the system. So whats the "correct" way?

Method 1:

try
{
    using (SqlConnection con = new SqlConnection(connectionString))
    {
        con.Open();

        using (SqlCommand command = new SqlCommand("StoredProcedure", con))
        {
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(new SqlParameter("foo", bar));
        }

        using (SqlDataReader reader = command.ExecuteReader())
        {   
            //do stuff
        }
    }
}
catch (Exception ex)
{
    //do stuff
}

Method 2:

// Variables
SqlCommand loComm;
SqlConnection loConn = null;
SqlDataReader loDR;

try
{
    // Init command
    loComm = new SqlCommand("foo");
    loComm.CommandType = CommandType.StoredProcedure;
    loComm.Parameters.AddWithValue("foo", bar);

    // Init conn
    loConn = new SqlConnection(String);
    loConn.Open();
    loComm.Connection = loConn;

    // Run command
    loDR = loComm.ExecuteReader();

    //do stuff           
}
catch (Exception ex)
{
    //do stuff
}

While both methods work I am not sure which one is the most appropriate to use. Is there a reason to use one over the other? The second method is cleaner and easier to understand to me, but it doesn't automatically run the iDispose() function when it is finished.

Edit: My question is different then the one suggested, because one approach uses the "using" statement while the other doesn't. So my question is directly related to whether or not to utilize the "using" statements when making a database connection.

Thanks, for all the responses.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
flyingweseal
  • 51
  • 2
  • 8
  • 2
    Oh god, don't even consider the second method. It's only cleaner in that it avoids error handling - that's a terrible trade-off. Using `using` on `IDisposable` objects should be the default approach. Embrace `using` and `try`-`finally` - you should use them far more often than `try`-`catch`, really. – Luaan Nov 24 '15 at 16:35
  • Possible duplicate of [try/catch + using, right syntax](http://stackoverflow.com/questions/4590490/try-catch-using-right-syntax) – Corbin March Nov 24 '15 at 16:36
  • 2
    `their response was "I don't know that's just how I do it"` - And they get paid for this? – David Nov 24 '15 at 16:39
  • 1
    @David about 5 years ago within our company, it came down from management that everything needed to be wrapped in a try catch, and exceptions were to be rethrown. To this day we still deal with lost stack traces from `throw ex` everywhere. So I can *completely* understand that people can get paid for this, unfortunately. – Jonesopolis Nov 24 '15 at 16:42
  • 1
    @David I totally agree.., they would never program on my team on for our company.. wow.. at least `Zephyr Brammer` asked a legit question and if I were him, I would not rely on fellow programmers whom just do but don't understand the `Why and the How` – MethodMan Nov 24 '15 at 16:43
  • @Jonesopolis, so how many `Managers in IT` do you know that can really code or understand code..? just because they `came down` with it doesn't make it right. a good / great developer would prove their case in my opinion and have examples of `Good practice vs Bad Practice` and coded properly In my opinion you can catch a lot of things ie StackTrace, Logs, TraceLogs...etc – MethodMan Nov 24 '15 at 16:45
  • @MethodMan I completely agree, and this occurred before I came on board. I'm just saying, I've seen how these things can happen in practice. – Jonesopolis Nov 24 '15 at 16:56

5 Answers5

13

Method 2 is simply incorrect and should be repaired.

When completed, you will be left with IDisposable instances that have not been disposed. Most likely, this will play havoc with the connection management that goes on behind the scenes with SqlConnection, especially if this code gets thrashed a lot before GC decides to step in.

If an instance is IDisposable, then it needs to be Disposed of, preferably in the smallest scope possible. Using using will ensure that this happens, even if the code malfunctions and exceptions are thrown.

A using statement:

using(var disposableInstance = new SomeDisposableClass())
{
    //use your disposable instance
}

is (give or take a few minor details) syntactic sugar for:

var disposableInstance = new SomeDisposableClass();
try
{
    //use your disposable instance
}
finally
{
    //this will definitely run, even if there are exceptions in the try block
    disposableInstance.Dispose();
}

Even if something goes wrong in the try block, you can be assured that the finally block will execute, thereby ensuring that your disposables are disposed, no matter what happens.

spender
  • 117,338
  • 33
  • 229
  • 351
  • As Luaan points out in one of the answers below, the finally{} should probably have a null check, just in case disposableInstance becomes null in the try{} – MutantNinjaCodeMonkey Nov 24 '15 at 16:48
  • @MutantNinjaCodeMonkey I don't believe that a null-check on that specific reference to the disposable would be equivalent, so I've updated my answer with "give or take a few minor details". – spender Nov 24 '15 at 16:50
  • @MutantNinjaCodeMonkey In fact, if you attempt to reassign a reference that was declared in a `using` statement (e.g. `using(var someRef = new SomeDisposable())`), the compiler will complain "Cannot assign to 'someRef' because it is a 'using' variable". By placing the reference declaration in a `using` statement, the reference becomes readonly. – spender Nov 24 '15 at 18:46
  • Well.. In your second example, it's possible to set disposableInstance to null, therefore it would throw an exception in the finally. It is also possible that the using statement could initialize the disposableInstance to null (not in your example, but say it was returned from a factory method or something). That case will compile and execute without throwing an exception too. I'd guess there's always a null check going on somewhere. :) – MutantNinjaCodeMonkey Nov 24 '15 at 19:15
  • At least for classes.. hehehe I suppose a struct can implement IDisposable and the Dispose() method would always be there. – MutantNinjaCodeMonkey Nov 24 '15 at 19:22
  • @MutantNinjaCodeMonkey Implementing `IDisposable` on a struct? There's a recipe for disaster, if ever I saw one! – spender Nov 24 '15 at 19:24
1

In the first example, if there is an exception thrown, the objects wrapped in the using blocks will be properly closed and disposed.

In the second, you will manually need to dispose of your objects.

One other thing worth mentioning is that if you were planning on disposing of your objects only when an exception is thrown, you will have objects that are not disposed of, so you would need to implement a try..catch..finally and dispose the objects within the finally block.

The first is the better option.

Ric
  • 12,855
  • 3
  • 30
  • 36
0

The first one will close the connection if an exception is thrown. The second one won't, so I'd say go with the first choice.

Bauss
  • 2,767
  • 24
  • 28
  • The first one will close the connection / dispose of regardless of an exception that's why it's wrapped in a `using` to handle auto disposing. this definitely is not an answer should be a comment at best.. – MethodMan Nov 24 '15 at 16:36
0

What the using block does is to warranty that the object Dispose method will always be invoked, no matter if an exception is thrown or not.

Dispose is a method used to clean up resources. In the case of a DB connection, the connection is released, which is really important.

So, the correct way in this case is using the using pattern.

The object included between the using parents mus be IDisposable whic means that it has a Dispose method that should be invoked when the object is no longer needed. If you don't invoke dispose, it will be disposde at any indeterminate time, when the garbage collector destroys the object. That's undesirable in case like a DB connection that must be closed as soon as possible.

The equivalen of usin is a try finally, which includes a call to Dispose within the finally block.

JotaBe
  • 38,030
  • 8
  • 98
  • 117
0

Reading here, it says:

As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

That sounds like the correct way is method 1.

JFischer00
  • 91
  • 9