为什么 SqlCommand.ExecuteNonQuery 抛出的 SqlException 包含所有 PRINT 作为错误?

发布于 2024-08-19 20:58:38 字数 763 浏览 6 评论 0原文

当我运行以下代码片段时,

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 of 0(相对于真正的错误为 18)

但是,如果我用 ExecuteScalar 替换 ExecuteNonQuery,我会得到预期的结果:

消息为 SQL_Error 并且我在 ex.Errors 中只有一个条目...

有什么方法可以避免 cmd.ExecuteNonQuery 的奇怪行为?

When I run the following snippet

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

I get the following message:

SQL_Error
A
B
C

and ex.Errors has 4 entries (The 3 SqlError's corresponding to the prints have a SqlError.Class of 0 (vs. 18 for the real error)

However, if I replace ExecuteNonQuery with ExecuteScalar, I get the expected result:

The message is SQL_Error and I only have one entry in ex.Errors...

Is there any way to avoid the strange behavior of cmd.ExecuteNonQuery??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

枫以 2024-08-26 20:58:38

不,你无法避免这种行为。它是 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 中的第一项

No you can't avoid this behavior. Its the result of the way TdsParser.ThrowExceptionAndWarning() is written

particularly this line

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

My guess is that for whatever reason one of the collection _error or _attentionErrors is empty for ExecuteScaler and its not for ExecuteNonQuery.

I'm sure if you poked around enough you could probably find out why.

In any case you seem to have the workaround already. Only use the first item in SQLExecption.Error

飘落散花 2024-08-26 20:58:38

ExecuteNonQuery 通常返回记录集,而 ExecuteScalar 返回第一行+第一列。

ExecuteNonQuery normally returns a recordset while ExecuteScalar returns the first row + first column.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文