Rethrow Exception

CA2200 : Rethrow to preserve stack details. That’s one recommendation that as a developer you might have seen when running Code Analysis on your solution.

So what does it mean ? What does the guilty code looks like and what is the correct way to throw exceptions. Lets start with incorrect code first.

Considering following Code.


    class Program
    {
        static void Main( string[] args)
        {
            try
            {
                new IntermediateClass().IntermediateMethod();
            }
            catch ( Exception Ex)
            {
               
                throw;
            }
        }
    }

    class IntermediateClass
    {
        public void IntermediateMethod()
        {
            try
            {
                new ErrorClass().ErrorMethod();
            }
           catch ( Exception Ex)
           {
                throw  Ex;
            }
        }
    }
    
    class ErrorClass
    {
        public void ErrorMethod()
        {
            int k = 1;
            int j = 3 / --k;
        }
    }
 

We have 3 classes, the main class which invokes a method of IntermediateClass, which in turns invokes method from ErrorClass. The ErrorMethod has been designed purposely to throw an error. It doesn’t implement an exception handling mechanism of its own, and the exception is caught by the Intermediate Class. The Intermediate Class, in turns, throws the exception back to the main class. The Code Analysis Tool has problem with this very same line, where the Intermediate Class throws the exception.

Every Exception Object contains a property called Stack Trace, which carries a list of method call hierarchy starting from the method which threw the exception to the method which caught the exception. If you were to analysis the stack trace of the exception caught in the Main Class, you would find something in similar lines.

“ExceptionHandling.IntermediateClass.IntermediateMethod() in <Path>\IntermediateClass.cs:line 21\r\n at ExceptionHandling. Program. Main (String[] args) in <Path>\Program.cs”

As you can observe, the stack trace doesn’t contains the references to the ErrorMethod, but rather it is reset and traces method starting from the point the exception is rethrown, that is from the intermediate method. In order to preserve the stack information, when you need to rethrow the exception without specifying the exception explicitly. Following would be the modification that would be required in Intermediate Method.


    class IntermediateClass
    {
        public void IntermediateMethod()
        {
            try
            {
                new ErrorClass().ErrorMethod();
            }
           catch ( Exception Ex)
           {
                throw ;
            }
        }
    }

Now if you were to view the stack trace now, the method list would look slightly different.

“ExceptionHandling.ErrorClass.ErrorMethod() in <path>\ErrorClass.cs:line 14\r\n at ExceptionHandling. IntermediateClass. IntermediateMethod() in <path>\IntermediateClass.cs:line 21\r\n at ExceptionHandling.Program.Main(String[] args) in <path>\Program.cs:line “

So next time you rethrow an exception, don’t forget to ensure the exception is not explicitly specified.

Batch Execution in Firebird

Executing a .sql file on Firebird Database can be quite a messy job. The lack of proper documentation and support would hurt you more when encountered issues and that is what I faced when I required to do execute contends of a .Sql File. Having understood that FbBatchExecution is the command I would required, I went to write following Function in C#.
public void ExecuteTransaction()
{
    try
    {
        if (m_cmd.Connection.State == System.Data. ConnectionState.Closed)
            m_cmd.Connection.Open();

        using ( FbTransaction fbTransaction = m_connnection.BeginTransaction())
        {
            FbScript script = new FbScript( this.ScriptFileContends);
            m_cmd.Transaction = fbTransaction;
            script.Parse();
            var BatchExecute = new FbBatchExecution(m_cmd.Connection, script);
            BatchExecute.Execute( true);
        }
    }
    catch ( Exception Ex)
    {
		throw Ex;
    }
}

This looked reasonable, I am reading out the Contends of the File using FbScript object and using the FbBatchExecution Object for bulk queries. I am managing the whole operation using FbTransaction. All seems well until I ran it and came up with following Exception.
“Execute requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized”
After hours of browsing, it turned out to be simple actually. All I needed for to add following lines.
 BatchExecute.CommandExecuting += delegate( object sender, CommandExecutingEventArgs args)
{
      args.SqlCommand.Transaction = fbTransaction;
};

The new Method would like following and you all set to go.
 public void ExecuteTransaction()
{
    try
    {
        if (m_cmd.Connection.State == System.Data. ConnectionState.Closed)
            m_cmd.Connection.Open();

        using ( FbTransaction fbTransaction = m_connnection.BeginTransaction())
        {
            FbScript script = new FbScript( this.ScriptFileContends);
            m_cmd.Transaction = fbTransaction;
            script.Parse();
            var BatchExecute = new FbBatchExecution(m_cmd.Connection, script);
			BatchExecute.CommandExecuting += delegate( object sender, CommandExecutingEventArgs args)
            {
                args.SqlCommand.Transaction = fbTransaction;
            };
            BatchExecute.Execute( true);
        }
    }
    catch ( Exception Ex)
    {
		throw Ex;
    }
}