Combine { using } statement and {try-catch} statement in C#

niceguy971
niceguy971 used Ask the Experts™
on
What would be the best way to combine  {try-catch} statement and { using } statement?

Just put { using } statement in try section??

    try 
    {
       // Put using statement here
       
    }
    catch (Exception ex) 
    {
       // handle exception
    }

Open in new window


The below code (I got it from http://www.aspsnippets.com/Articles/Export-data-from-SQL-Server-to-Text-file-in-C-and-VBNet.aspx)  does Not handle Exceptions. What would be the best way to fix it??

Put block { using (SqlConnection con = new SqlConnection(constr)) }  in try section??

    string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    using (SqlConnection con = new SqlConnection(constr))
    {
        using (SqlCommand cmd = new SqlCommand("SELECT * FROM Customers"))
        {
            using (SqlDataAdapter sda = new SqlDataAdapter())
            {
                cmd.Connection = con;
                sda.SelectCommand = cmd;
                using (DataTable dt = new DataTable())
                {
                    sda.Fill(dt);
 
                    //Build the Text file data.
                    string txt = string.Empty;
 
                    foreach (DataColumn column in dt.Columns)
                    {
                        //Add the Header row for Text file.
                        txt += column.ColumnName + "\t\t";
                    }
 
                    //Add new line.
                    txt += "\r\n";
 
                    foreach (DataRow row in dt.Rows)
                    {
                        foreach (DataColumn column in dt.Columns)
                        {
                            //Add the Data rows.
                            txt += row[column.ColumnName].ToString() + "\t\t";
                        }
 
                        //Add new line.
                        txt += "\r\n";
                    }
                }
            }
        }
    }

Open in new window


Thanks
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
AndyAinscowFreelance programmer / Consultant
Commented:
>>Just put { using } statement in try section??

Yes and then again no.
The using will dispose of the object when the using block is left.  So should an exception be thrown then do you need the object created in the using statement in the catch.  Yes - using outside of try, no - using inside of try is OK.


>>What would be the best way to fix it??
Probably to put it all inside a try block.  See the first part of my comment.
Yes. I would suggest to go with the first option.

Enclosing your Using statement with {try-catch} statement sounds good.
Karrtik IyerSoftware Architect
Commented:
There are two options as you might have also identified. I have shown both of them below.
I prefer the option 2 which is try/catch outside the using statement, this has served us well. The reasons are:
1> Normally in my experience and our scenarios catch statement used to take an action of unknown duration, like display of  message to the user.
2> We wanted to dispose of our resources before doing that.
In these scenarios for us the try-catch block is usually in a different method further up the call stack from the using. It is not usual for a method to know how to handle exceptions that occur within it like below.
private void LoadAction()
{
    try
    {
        LoadFile(myFile); // The using statement will appear somewhere in here.
    }
    catch (IOException ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Open in new window

3. Also if try and catch is within the using statement, the other problem could be that even last "}" (curly brace) of using block can thrown exceptions as explained in this MSDN article.Last curly brace issue

But then are reasons when we may want to use option 1 (try catch inside using statement) as well, such cases are:
1> Catch statement needs to access the variable declared in a using statement.
2> Catch statement needs the object referenced in the using block before it being disposed.


option 1:
using (var myObject = new MyClass())
{
   try
   {
      // something here...
   }
   catch(Exception ex)
   {
      // Handle exception
   }
}

Open in new window

Option 2:
try
{
   using (var myObject = new MyClass())
   {
      // something here...
   }
}
catch(Exception ex)
{
   // Handle exception
}

Open in new window

Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

PawełI Design & Develop Software
Commented:
an alternative approach you can use; is to have a finally block to dispose your connection

var con = new SqlConnection(constr);

try{
  //stuff with your connection
}
catch(Exception ex){
  //handle exceptions
}
finally{
  con.Dispose();
}

the finally block will always fire regardless if there's an exception, that being said i'd probably still wrap the using inside the try, but it's your call.

Open in new window

Commented:
Since a using statement is really nothing more than a try...finally block of code; e.g. -
using (var command = new SqlCommand("SELECT * FROM Customers"))
{
	// Do something with our command
}

// When compiled becomes
SqlCommand command;
try
{
	command = new SqlCommand("SELECT * FROM Customers");
}
finally
{
	if (command != null)
	{
		command.Dispose()
	}
}

Open in new window

You can enclose your using statement in a try...catch without much worry with regards to exception bubbling (as alluded to by Andy).

What is meant by this is that any exception thrown from a using statement would act the same as any exception thrown from any method, it bubbles up the stack until it reaches the most internal implementation of catch that matches it's exception signature.

What do I mean by this?  Consider the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace EE_Q28909760
{
	class Program
	{
		static void Main(string[] args)
		{
			try
			{
				try
				{
					try
					{
						using (Branch branch = new Branch())
						{
							branch.Add(null);
						}
						throw new ArgumentException();
					}
					catch (RootException ex)
					{
						Console.WriteLine(ex);
					}
				}
				catch (BranchException ex)
				{
					Console.WriteLine(ex);
				}
			}
			finally
			{
				Console.WriteLine("Application will close now.");
				Console.ReadLine();
			}
		}
	}

	class Branch : List<Leaf>, IDisposable
	{
		public Branch() { ;}
		public Branch(int capacity) : base(capacity) { ;}
		public Branch(IEnumerable<Leaf> collection) : base(collection) { ;}

		public void Add(Leaf item)
		{
			if (item == null)
				throw new BranchException("Cannot add null leaf", new LeafException("invalid leaf", new ArgumentNullException()));
			base.Add(item);
		}

		public void Dispose()
		{
			for (int i = Count - 1; i > 0; i--)
				this[i].Dispose();
		}
	}

	class Leaf : IDisposable
	{
		private string _name;
		public string Name
		{
			get { return _name; }
			set 
			{
				if (value == null)
					throw new LeafException("Leaf name cannot be null", new ArgumentNullException());

				if (string.IsNullOrWhiteSpace(value))
					throw new LeafException("Leaf cannot be unnamed", new ArgumentException());

				_name = value; 
			}
		}

		public Leaf(string name)
		{
			if (name == null)
				throw new LeafException("Leaf name cannot be null", new ArgumentNullException());

			if (string.IsNullOrWhiteSpace(name))
				throw new LeafException("Leaf cannot be unnamed", new ArgumentException());

			Name = name;
		}

		public void Dispose()
		{
			Name = string.Empty;
		}
	}

	class RootException : Exception
	{
		public RootException() { ;}
		public RootException(string message) : base(message) { ;}
		public RootException(string message, BranchException branch) : base(message, branch) { ;}
		public RootException(SerializationInfo info, StreamingContext context) : base(info, context) { ;}
	}

	class BranchException : Exception
	{
		public BranchException() { ;}
		public BranchException(string message) : base(message) { ;}
		public BranchException(string message, LeafException leaf) : base(message, leaf) { ;}
		public BranchException(SerializationInfo info, StreamingContext context) : base(info, context) { ;}
	}

	class LeafException : Exception
	{
		public LeafException() { ;}
		public LeafException(string message) : base(message) { ;}
		public LeafException(string message, Exception ex) : base(message, ex) { ;}
		public LeafException(SerializationInfo info, StreamingContext context) : base(info, context) { ;}
	}
}

Open in new window

When I run this, the exception caused by creating a null leaf gets caught by the middle try block as it is the most internal try block that catches the BranchException signature (the most inner try...catch, catches a RootException); e.g. -Capture.JPGNow if I create a real leaf that follows the rules, I have no catches that will catch an ArgumentException, so what happens next is based upon the WER (Windows Error Reporting) configuration; e.g. -This is what happens on my system when an unhandled exception is encountered.Or if I try to create an invalid leaf, again no try...catch blocks catch a LeafException, so I should expect similar WER results as those for forcing an ArgumentException -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace EE_Q28909760
{
	class Program
	{
		static void Main(string[] args)
		{
			try
			{
				try
				{
					try
					{
						using (Branch branch = new Branch())
						{
							branch.Add(new Leaf(""));
						}
					}
					catch (RootException ex)
					{
						Console.WriteLine(ex);
					}
				}
				catch (BranchException ex)
				{
					Console.WriteLine(ex);
				}
			}
			finally
			{
				Console.WriteLine("Application will close now.");
				Console.ReadLine();
			}
		}
	}

	class Branch : List<Leaf>, IDisposable
	{
		public Branch() { ;}
		public Branch(int capacity) : base(capacity) { ;}
		public Branch(IEnumerable<Leaf> collection) : base(collection) { ;}

		public void Add(Leaf item)
		{
			if (item == null)
				throw new BranchException("Cannot add null leaf", new LeafException("invalid leaf", new ArgumentNullException()));
			base.Add(item);
		}

		public void Dispose()
		{
			for (int i = Count - 1; i > 0; i--)
				this[i].Dispose();
		}
	}

	class Leaf : IDisposable
	{
		private string _name;
		public string Name
		{
			get { return _name; }
			set 
			{
				if (value == null)
					throw new LeafException("Leaf name cannot be null", new ArgumentNullException());

				if (string.IsNullOrWhiteSpace(value))
					throw new LeafException("Leaf cannot be unnamed", new ArgumentException());

				_name = value; 
			}
		}

		public Leaf(string name)
		{
			if (name == null)
				throw new LeafException("Leaf name cannot be null", new ArgumentNullException());

			if (string.IsNullOrWhiteSpace(name))
				throw new LeafException("Leaf cannot be unnamed", new ArgumentException());

			Name = name;
		}

		public void Dispose()
		{
			Name = string.Empty;
		}
	}

	class RootException : Exception
	{
		public RootException() { ;}
		public RootException(string message) : base(message) { ;}
		public RootException(string message, BranchException branch) : base(message, branch) { ;}
		public RootException(SerializationInfo info, StreamingContext context) : base(info, context) { ;}
	}

	class BranchException : Exception
	{
		public BranchException() { ;}
		public BranchException(string message) : base(message) { ;}
		public BranchException(string message, LeafException leaf) : base(message, leaf) { ;}
		public BranchException(SerializationInfo info, StreamingContext context) : base(info, context) { ;}
	}

	class LeafException : Exception
	{
		public LeafException() { ;}
		public LeafException(string message) : base(message) { ;}
		public LeafException(string message, Exception ex) : base(message, ex) { ;}
		public LeafException(SerializationInfo info, StreamingContext context) : base(info, context) { ;}
	}
}

Open in new window

Which results in -Capture.JPG-saige-

Author

Commented:
Thanks!

Author

Commented:
Thanks!!

Author

Commented:
Thanks

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial