I, Codemonkey

Codemonkeying Around
posts - 4, comments - 4, trackbacks - 0

My Links

News

Archives

Custom Exceptions and Exception Wrapping

I work almost only with code written by predecessors at my job. There's good code and bad code. Recently, I've been trying to clean up the exceptions. Just about everything is throw Exception(<my message here>) instead of customized exceptions, so you never really know what you're catching. It could be an IO exception, a null pointer, or whatever. The message is generally something that can be displayed to the user without them becoming confused, but with a mix of "good" message exceptions and "bad" ones (for example something generated by SQL), its impossible to dig through them and see what I need and what the user needs.

So, while consolidating much of this into an error handling class that will aid us both, I've been looking into creating my own exceptions and going over some code I've never really had a chance to examine before. I'm starting with database access because that's been the biggest problem for me in this regard. Here's a snip of part of our back end that opens a database connection with some stuff cut out to make it more readable.


        /// <summary>
        /// Open the database.
        /// </summary>
        /// <param name="tDatabaseType">Which database to connect to</param>
        public void Open(DBType tDatabaseType)
        {
            try
            {
                _Connection.Open();
                _Command = new OleDbCommand();
                _Command.Connection = _Connection;
            }
            catch(Exception ex)
            {
                _lastError = ex.Message.ToString();
            }
        }


I didn't even realize until now that there was no exception being thrown when it can't connect to the database. This isn't how I'd like to do things, especially considering that I want to centralize exception handling. This way, the connection never happens, but I don't know that unless I either check _lastError or until I try to use the connection and get an exception thrown at me. First, I'm going to create my own custom exception.

using System;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Text;

namespace DecoCore.Err
{
    [Serializable]
    public class DatabaseNotFoundException : Exception
    {
        /// <summary>
        /// The database could not open a connection
        /// </summary>
        public DatabaseNotFoundException()
            : base()
        {
        }
        /// <summary>
        /// The database could not open a connection
        /// </summary>
        /// <param name="sMsg">Message displayed to user</param>
        public DatabaseNotFoundException(string sMsg)
            : base(sMsg)
        {
        }
        /// <summary>
        /// The database could not open a connection
        /// </summary>
        /// <param name="sMsg">Message displayed to user</param>
        /// <param name="eInnerException">exception causing this exception</param>
        public DatabaseNotFoundException(string sMsg,
            Exception eInnerException)
            : base(sMsg, eInnerException)
        {
        }
        /// <summary>
        /// The database could not open a connection
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        protected DatabaseNotFoundException(SerializationInfo info,
            StreamingContext context)
            : base(info, context)
        {
        }
    }
}

Very simple and straightforward. Now, what I'll do is go back to the first code block above, the one that opens a connection to a database supplied to it through an enumeration.

        /// <summary>
        /// Open the database.
        /// </summary>
        /// <param name="tDatabaseType">Database Type</param>
        public void Open(DBType tDatabaseType)
        {
            try
            {
                _Connection.Open();
                _Command = new OleDbCommand();
                _Command.Connection = _Connection;
            }
            catch (OleDbException ex)
            {
                _lastError = ex.Message.ToString();
                throw new DatabaseNotFoundException("Could not connect to the database.", ex);
            }
            catch (Exception ex)
            {
                _lastError = ex.Message.ToString();
                throw;
            }
        }

Luckily for me, every call to Open is already in a try/catch even though it didn't throw an exception previously.

Now when I get to call my error handler after this propagates up, I know there was an exception thrown and I know exactly why it was thrown. The user doesn't get strange SQL errors displayed, instead they get a simple "Could not connect to database" which they will understand, and I can now, very importantly, extract the underlying OleDbException from the DatabaseNotFoundException and get the debugging information I need for proper logging of errors.
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Print | posted on Tuesday, July 03, 2007 9:05 AM |

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification:
 
 

Powered by: