25

I know that Using statement disposes out the object that is being created. Like if I wanted to do something like this:

    Using(SqlConnection conn = new SqlConnection(connString))
    {
      //some code
      //How to show the users if conn is not opened up or generated some kind of error?
    }

How to show the users if conn is not opened up or generated some kind of error?

RG-3
  • 6,088
  • 19
  • 69
  • 125

9 Answers9

25

There's nothing special about code written inside a using block - just use a try.catch to handle exceptions:

using(SqlConnection conn = new SqlConnection(connString))
{
    try
    {
        conn.Open();
        // do more stuff here......

    }
    catch(SqlException sqlEx)
    {
       // log error and possibly show to user in a MessageBox or something else
    }
}

The using(...) { ... } block itself is designed only to ensure that the resource / object it "encapsulates" is properly disposed of when it's no longer needed. There's is nothing you can do with the using statement itself to make it handle errors.

So if you expect that just creating the object could fail, then you'd have to put the entire using block inside the try ... catch block , or fall back to a try ... catch ... finally block and ensure proper disposal yourself (as Adam suggested in his answer).

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Why we are using try/catch inside Using? – RG-3 Apr 17 '12 at 15:01
  • 5
    +1 ... it's not only not special but even good practise to use try/catch in a using-statement. Disposing objects and handling exceptions are different concepts. – Tim Schmelter Apr 17 '12 at 15:02
  • 2
    @Raj Because a Try/Catch is how you catch an Exception. A Using is only a Try/Finally (without a catch). If your question is why isn't it outside the using, it's because creating the connection isn't likely to cause an error, opening it is. – Servy Apr 17 '12 at 15:02
  • 1
    @Raj why wouldn't you use try/catch inside a using block? – phoog Apr 17 '12 at 15:04
  • 2
    @Raj Because that's where it goes. The using statement is a shorthand for a try/finally block, but provides no mechanism for handling exceptions. This code is equivalent to a try/catch/finally, but does the "right thing" in the finally block automagically. – Preston Guillot Apr 17 '12 at 15:04
  • If I was only covering the `connection.Open()` out of a very large piece of code I would embed the try-catch inside the using covering *only* the connection open, otherwise I would bin the using and write it all by hand. – Adam Houldsworth Apr 17 '12 at 15:17
  • 1
    @marc_s Yes, it is obvious how to catch exceptions inside using block. But one caveta worth mentioning is that exception might occur in using statement itself. For example: construnctor SqlConnection() might be passed invalid connection string or whatever else. –  Jan 29 '17 at 16:17
12

using doesn't offer any backdoor into the catch.

Simply expand it manually (no point in having the try/catch inside the using IMO):

SqlConnection conn = null;

try
{
    conn = new SqlConnection("");
}
catch ...
{

}
finally
{
    if (conn != null)
        conn.Dispose();
}

I favour this over wrapping the using in a try-catch or embedding a try-catch in the using most of the time to avoid having the code end up with a nested try-catch once compiled. If you only need to cover a very small subset of a large piece of code within a using, however, I'd be more granular and embed it.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
8
class SqlConnection
{
   using(sqlConnection)
   {

   }
}

class Consumer
{
   try
  {

  }
  catch(SqlException)
  {

  }

}

It is up to the consumer of the class to decide what to do with the exception.

Sandeep
  • 7,156
  • 12
  • 45
  • 57
6

As other answers have stated, just add a normal try/catch.

However, I would add that this is the wrong place to put that try/catch, especially if your goal is "show the users" a message. Let the exception happen at this level, and allow it to bubble up the stack to code that's in a better position to know how to respond to it.

In other words, leave your code sample as it is. Don't add anything new... to that method. But perhaps the code that calls this method should be thinking about how to handle an exception ... any exception... from the database.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
3

Just in the normal way:

Either

try
{
    using(SqlConnection conn = new SqlConnection(connString)) 
    { 
      //some code        
    } 
}
catch (Exception exc)
{
    //handle error
}

or

using(SqlConnection conn = new SqlConnection(connString)) 
{ 
    try
    {
        //some code 
    }
    catch (Exception exc)
    {
        //handle error
    }                
} 
Widor
  • 13,003
  • 7
  • 42
  • 64
  • 2
    @Widor: This won't handle if an exception is thrown at `SqlConnection conn = new ...` – Ayush Apr 17 '12 at 15:04
  • Well, it depends what you do in there - maybe you want to catch a different potential exception (not related to SQL) for example. – Widor Apr 17 '12 at 15:04
2

Thats just the same way you would do it without.

using(SqlConnection conn = new SqlConnection(connString))
{
  try{
    //some code
  }
  catch(SqlException e)
    MessageBox.Show(e.Message);
}
Matten
  • 17,365
  • 2
  • 42
  • 64
0

You don't do it inside the using

try
{
    using(SqlConnection conn = new SqlConnection(connString))
    {
        // Some code for when "conn" is succesfully instantiated
    }
}
catch (SomeSpecificConnectionInstantiationException ex)
{
    // Use ex to handle a bizarre instantiation exception?
}       
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • You can write try/catch inside the using. I believe! – RG-3 Apr 17 '12 at 15:04
  • 2
    You can but, not to catch an exception in the using instantiation – Jodrell Apr 17 '12 at 15:05
  • @Jodrell But a SqlConnection won't generally throw an exception in its constructor. The only exception that you'd likely be getting is in the expression for the parameter. – Servy Apr 17 '12 at 15:07
  • 1
    This code doesn't allow the catch block access to the SqlConnection object that generated the exception, as well. – Preston Guillot Apr 17 '12 at 15:10
  • @Servy, if its the familiar `SqlConnection` from the normal namespace (which it probably is) then I agree. However, could be some other `SqlConnection` – Jodrell Apr 17 '12 at 15:10
  • @Jodrell - No, this would be true of **any** SqlConnection type, because the using statement also creates a scope block. If you put the try/catch outside of the using block, the created object will not be available to the catch block, no matter what type. I'd love to see Microsoft add a using/catch construct. – Joel Coehoorn Apr 17 '12 at 15:13
  • @JoelCoehoorn, read the point I'm answering, not by the order they are listed. – Jodrell Apr 17 '12 at 15:18
  • @Preston Guillot, theres nothing to stop any number of nested blocks inside the using. The external `try\catch` exists only to catch some bizarre instantiation exception I thought the OP was asking about. In that situation `conn` would be indeterminate anyhow. – Jodrell Apr 17 '12 at 15:24
  • @Jordell You're right, but I'd say that if you're worrying about catching a potential exception in the ctor the answer that you voted for is more correct. With that structure you can just chain catch blocks together, with only the one for your SomeSpecificConnectionInstantiationException needing to handle the case where conn is indeterminate. – Preston Guillot Apr 17 '12 at 20:55
0

When you embed the using() block inside a try/catch, the using() block will indeed guarantee that Dispose is called. However, if non-managed code anywhere within your using block throws an exception, using() will just eat it and it won't reach your catch. Use try/catch inside the using() block, skip using() and do a try/catch/finally, or use the odd "using() try" syntax with a catch block (which leaves you with an odd number of brackets and is likely to confuse the heck out of mid-level programmers who later encounter it.

-3

It is a good practice to use the try{}catch(){} inside the using statement if you want to catch an exception thrown by the code inside the using block. Now, consider the following two examples - that explains why try-catch block inside the using statement is a good practice.

Example 1

       try{
           using(SomeObject so = new SomeObject){
              // Perform some tasks
           }
       }catch(SomeException objSomeException){
             // Perform some actions, if exception occurs
       }

Example 2

       using(SomeObject so = new SomeObject){
           try{    
               // Perform some tasks
              }catch(SomeException objSomeException){
                   // Perform some actions, if exception occurs
              }
       }

Now, if an exception occurs while performing some tasks inside the using statement, will both example have the same results. The simple answer is no, reason???

When an exception occurs in the example 1, it is caught by the catch block - without reaching the end of the using block. Therefore, the someObject in example 1 will not get disposed properly. Even if CLR is generous (which you should not count on) - the memory used by the someObject in the example 1 will not be recovered (or maximum it will end up in Generation 2 GC collection).

Where in case of the example 2, the catch block is inside the using statement. That means that the execution will reach the end of the using block. Therefore, your object will be disposed and you won't have to worry about the memory leakage (spoilage,

  • 9
    This is wrong. If an error happens in the using, the objectd will be disposed of by the implicit `finally` block of the `using`, and the exception will be managed by the outer `catch`. In the second case the exception will be managed by the inner `catch` block, and the implicit `finally` of the `using` will dispose of it later. So, the only difference is that in the second sample `catch` the object is still available, so you can still use it to handle the exception. In the first sample, the object will be no longer available in the catch block. No more differences. – JotaBe Jan 14 '14 at 12:02