Question

This legacy code is called from a gazillion places in the app:

    public void DBCommand(string dynSQL, bool Silent)
    {
        checkConnection();
        SqlCeCommand cmd = objCon.CreateCommand();
        SqlCeTransaction trans = this.GetConnection().BeginTransaction();
        cmd.Transaction = trans;

        try
        {
            cmd.CommandText = dynSQL;
            cmd.ExecuteNonQuery();
            trans.Commit();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                string.Format("DBCommand Except in DBConnection.DBCommand: {0}. InnerException: {1}", ex.Message, ex.InnerException));//TODO: Remove
            try 
            {
                trans.Rollback();
            }
            catch (SqlCeException) 
            {
                // Handle possible exception here
            }
//              MessageBox.Show(
//                  string.Format("DBCommand Except in DBConnection.DBCommand: {0}. InnerException: {1}", ex.Message, ex.InnerException));//TODO: Remove
                WriteDBCommandException(dynSQL, ex, Silent);
            }
        }

When a particular file is loaded and its contents inserted into a database, I get this message five times. Yet the exception's Message and InnerException are always empty strings.

I even (somewhat superstitiously or illogically, perhaps) moved the MessageBox.Show() from one location to another to see if that would make any difference (it doesn't).

The exception displays, but without giving any useful information about what the problem is; I've looked (manually, or more precisely, I guess literally scanned optically) at the data in question, and it all seems okay.

So why is this exception message weeping and wailing, but without being communicative about what the problem is, like a colicky but mute baby (mouth wide open, tears streaming down, but no sound escaping)?

UPDATE

Okay, I adapted ErikEJ's code snippet (could not use HelpLink or StringIsNullOrEmpty as I'm using tools from a time long, long, ago, in the days of Alley Oop, Bertha Butt, and Artie Shaw):

            // from method that throws the exception
            catch (SqlCeException sqlfail)
            {
                MessageBox.Show(GetSQLCEErrorInfo(sqlfail));
            }
            catch (Exception ex)
. . .

        public static string GetSQLCEErrorInfo(SqlCeException args)
        {
            SqlCeErrorCollection errorCollection = args.Errors;

            StringBuilder bld = new StringBuilder();
            Exception inner = args.InnerException;

            if (null != inner)
            {
                bld.Append("\nInner Exception: " + inner.ToString());
            }
            // Enumerate the errors to a message box.
            foreach (SqlCeError err in errorCollection)
            {
                bld.Append("\n Error Code: " + err.HResult.ToString("X", 
System.Globalization.CultureInfo.InvariantCulture));
                bld.Append("\n Message   : " + err.Message);
                bld.Append("\n Minor Err.: " + err.NativeError);
                bld.Append("\n Source    : " + err.Source);
                // Enumerate each numeric parameter for the error.
                foreach (int numPar in err.NumericErrorParameters)
                {
                    if (0 != numPar) bld.Append("\n Num. Par. : " + numPar);
                }
                // Enumerate each string parameter for the error.
                foreach (string errPar in err.ErrorParameters)
                {
                    if ((null != errPar) && (errPar.Trim() != string.Empty))  //IsNullOrEmpty(errPar))
                    {
                        bld.Append("\n Err. Par. : " + errPar);
                    }
                }
            }
            return bld.ToString();
        }

...and I see the following:

Error Code: 80040E14
Message : There was an error parsing the query. [Token line number, Token line offset,, Token in error,,]
Minor Err.: 25501
Source : Microsoft SQL Server 2000 Windows CE Edition
Num. Par. : 1
Num. Par. : 47
Err. Par. " [

...then:

Exception: SLQ Server CE does not support parallel transactions.
Location. DBConnection.GetInstance(siteNo)

(I get both of those twice); but why only twice? It inserts a few hundred records...one would think that if it would fail once, it would fail every time.

Was it helpful?

Solution

You are doing it wrong, You need to catch the more specialized SqlCeException caused by ExecuteNonQuery before catching the general Exception. And for SqlCeExcpetion, special handling is required, you can use something like this to get all relevant info:

public static string ShowErrors(System.Data.SqlServerCe.SqlCeException e)
{
System.Data.SqlServerCe.SqlCeErrorCollection errorCollection = e.Errors;

StringBuilder bld = new StringBuilder();
Exception inner = e.InnerException;

if (!string.IsNullOrEmpty(e.HelpLink))
{
    bld.Append("\nCommand text: ");
    bld.Append(e.HelpLink);
}

if (null != inner)
{
    bld.Append("\nInner Exception: " + inner.ToString());
}
// Enumerate the errors to a message box.
foreach (System.Data.SqlServerCe.SqlCeError err in errorCollection)
{
    bld.Append("\n Error Code: " + err.HResult.ToString("X", System.Globalization.CultureInfo.InvariantCulture));
    bld.Append("\n Message   : " + err.Message);
    bld.Append("\n Minor Err.: " + err.NativeError);
    bld.Append("\n Source    : " + err.Source);

    // Enumerate each numeric parameter for the error.
    foreach (int numPar in err.NumericErrorParameters)
    {
        if (0 != numPar) bld.Append("\n Num. Par. : " + numPar);
    }

    // Enumerate each string parameter for the error.
    foreach (string errPar in err.ErrorParameters)
    {
        if (!string.IsNullOrEmpty(errPar)) bld.Append("\n Err. Par. : " + errPar);
    }
  }
  return bld.ToString();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top