Почему SqlException, выдаваемое SqlCommand.ExecuteNonQuery, содержит все PRINT как ошибки? - PullRequest
3 голосов
/ 01 февраля 2010

Когда я запускаю следующий фрагмент

try
{
 using (SqlConnection conn = new SqlConnection("I'm shy"))
 {
  conn.Open();

  using (SqlCommand cmd = conn.CreateCommand())
  {
   cmd.CommandText = "PRINT 'A';PRINT 'B';PRINT 'C';RAISERROR('SQL_Error', 18, 1)";
   cmd.ExecuteNonQuery();
  }
 }
}
catch (SqlException ex)
{
 MessageBox.Show(ex.Message);
}

Я получаю следующее сообщение:

SQL_Error
A
B
C

и ex.Errors имеет 4 записи (3 SqlError, соответствующие отпечаткам, имеют SqlError.Class 0 (против 18 для реальной ошибки)

Однако, если я заменю ExecuteNonQuery на ExecuteScalar, я получу ожидаемый результат:

Сообщение SQL_Error, и у меня есть только одна запись в ex.Errors ...

Есть ли способ избежать странного поведения cmd.ExecuteNonQuery ??

Ответы [ 2 ]

1 голос
/ 03 февраля 2010

Нет, вы не можете избежать этого поведения. Это результат того, как TdsParser.ThrowExceptionAndWarning () записывается

особенно эта строка

  bool breakConnection = this.AddSqlErrorToCollection(ref temp, ref this._errors) | this.AddSqlErrorToCollection(ref temp, ref this._attentionErrors);
        breakConnection |= this.AddSqlErrorToCollection(ref temp, ref this._warnings);
        breakConnection |= this.AddSqlErrorToCollection(ref temp, ref this._attentionWarnings);

Я предполагаю, что по какой-либо причине один из наборов _error или _attentionErrors пуст для ExecuteScaler, а не для ExecuteNonQuery.

Я уверен, что если ты побродишь достаточно, ты, наверное, узнаешь почему.

В любом случае, кажется, у вас уже есть обходной путь. Используйте только первый элемент в SQLExecption.Error

0 голосов
/ 01 февраля 2010

ExecuteNonQuery обычно возвращает набор записей, тогда как ExecuteScalar возвращает первую строку + первый столбец.

...