Почему это исключение не является ни молчаливым, ни информационным?

Этот унаследованный код вызывается из огромного количества мест в приложении:

    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);
            }
        }

Когда определенный файл загружается и его содержимое вставляется в базу данных, я получаю это сообщение пять раз. Тем не менее, Message и InnerException исключения всегда являются пустыми строками.

Я даже (возможно, несколько суеверно или нелогично) переместил MessageBox.Show() из одного места в другое, чтобы посмотреть, будет ли это иметь какое-либо значение (это не имеет значения).

Исключение отображается, но не дает никакой полезной информации о проблеме; Я просмотрел (вручную или, точнее, я полагаю, буквально отсканировал оптически) данные, о которых идет речь, и все вроде бы в порядке.

Так почему же это сообщение об исключении плачет и плачет, но не говорит о том, в чем проблема, как колики, но немой ребенок (рот широко открыт, слезы текут, но не издают ни звука)?

ОБНОВИТЬ

Хорошо, я адаптировал фрагмент кода ErikEJ (не смог использовать HelpLink или StringIsNullOrEmpty, поскольку я использую инструменты давным-давно, во времена Элли Ооп, Берты Батт и Арти Шоу):

            // 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();
        }

... и я вижу следующее:

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. " [

...потом:

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

(Я получаю оба из них дважды); но почему только дважды? Он вставляет несколько сотен записей... можно было бы подумать, что если он потерпит неудачу один раз, он будет ошибаться каждый раз.


person B. Clay Shannon    schedule 04.06.2013    source источник
comment
какое исключение? что такое сообщение? что в файле?   -  person Jason    schedule 04.06.2013
comment
Я не знаю ответа на ваш вопрос, но вот что нужно учитывать: когда вызов базы данных завершается сбоем, база данных не знает, является ли сбой ошибкой или результатом атаки враждебной стороны, пытающейся подорвать базу данных. Если вы находитесь в последнем случае, последнее, что вы хотите сделать, это предоставить злоумышленнику подробную информацию о характере сбоя; они собираются использовать это, чтобы создать лучшую атаку. Если это настоящая ошибка, вы нужно сообщить подробную информацию. База данных может не перейти в безопасный режим, потому что она не знает, что клиент безопасен.   -  person Eric Lippert    schedule 04.06.2013
comment
@Jason: Вот чего я не знаю - он мне не скажет.   -  person B. Clay Shannon    schedule 04.06.2013
comment
да, упс, ессно, вы не знаете исключения. но знаете ли вы, что в файле? Вы пытались использовать профилировщик, чтобы увидеть, что происходит?   -  person Jason    schedule 04.06.2013
comment
@Eric: Хороший вопрос; в этом случае я думаю, что враждебная сторона атакует бывшего программиста (IOW, непреднамеренная враждебность, например, когда лось наступает на кролика).   -  person B. Clay Shannon    schedule 04.06.2013
comment
я не знаю, будет ли это работать с CE, или есть ли другие инструменты, подобные этому, разработанные для CE. но по сути это позволяет вам отслеживать, что происходит с базой данных в режиме реального времени: msdn. microsoft.com/en-us/library/ms181091.aspx   -  person Jason    schedule 04.06.2013
comment
Этот метод принципиально нарушен в более важном смысле: он заставляет вас создавать SQL-запросы, уязвимые для SQL-инъекций. Метод должен включать еще один аргумент для принятия данных параметров и код для включения этих данных в запрос.   -  person Joel Coehoorn    schedule 04.06.2013
comment
@Joel: Да, вы правы, но все приложение сломано и практически не подлежит ремонту; мое прозвище для него Шалтай-Болтай. Я не прикасаюсь к нему больше, чем мне абсолютно необходимо, потому что, если я ткну его в живот, его палец начинает чесаться, и в результате рефлекторной реакции я получаю пинок прямо в живот (или хуже).   -  person B. Clay Shannon    schedule 04.06.2013
comment
Все королевские лошади и все королевские люди не смогли снова собрать Шалтая-Болтая. До недавнего времени я никогда не понимал эту мудрую чушь.   -  person B. Clay Shannon    schedule 04.06.2013


Ответы (1)


Вы делаете это неправильно. Вам нужно поймать более специализированное исключение SqlCeException, вызванное ExecuteNonQuery, прежде чем поймать общее исключение. А для SqlCeExcpetion требуется специальная обработка, вы можете использовать что-то вроде этого, чтобы получить всю необходимую информацию:

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();
}
person ErikEJ    schedule 04.06.2013
comment
Спасибо; Я обновил свой пост адаптацией этого и моих выводов. - person B. Clay Shannon; 04.06.2013
comment
Отлично, теперь вы можете правильно решить проблему, проверить sql, чтобы увидеть, что с ним не так. - person ErikEJ; 04.06.2013