如何在C#中捕获SQLException?

时间:2011-05-11 10:38:05

标签: c# sql-server

这里我试图在SMO Ojects.In Sqlserver中使用innerexception捕获sql异常 我收到此错误消息

Msg 121, Level 15, State 1, Procedure test_sp_syntaxtext, Line 124
The select list for the INSERT statement contains more items than the insert list.

但是使用此代码

catch (Exception ex)
          {
           ErrorFlag = true;
           //ex.Source.ToString();
           e2dInsertAndGenerateErrorLog(ex.InnerException.Message.ToString(), FileName, "CHECKINAPPLY", PathName, "ErrorLog.Err");
          }

我得到了这个

The select list for the INSERT statement contains more items than the insert list.

我还需要缓存此行

Msg 121, Level 15, State 1, Procedure test_sp_syntaxtext, Line 124

有什么建议吗?

编辑:

  StreamReader str = new StreamReader(FiletextBox.Text.ToString());
  string script = str.ReadToEnd();
  str.Dispose();
  SqlConnection conn = new SqlConnection("Data Source=xx;database=xxx;User id=sx;Password=xxxx");
  Server server = new Server(new ServerConnection(conn));
  server.ConnectionContext.ExecuteNonQuery(script);

6 个答案:

答案 0 :(得分:8)

使用SQLException

    catch (SqlException ex)
    {
        for (int i = 0; i < ex.Errors.Count; i++)
        {
            errorMessages.Append("Index #" + i + "\n" +
                "Message: " + ex.Errors[i].Message + "\n" +
                "LineNumber: " + ex.Errors[i].LineNumber + "\n" +
                "Source: " + ex.Errors[i].Source + "\n" +
                "Procedure: " + ex.Errors[i].Procedure + "\n");
        }
        Console.WriteLine(errorMessages.ToString());
    }

答案 1 :(得分:1)

catch (SqlException ex) { ... }

答案 2 :(得分:1)

查看您在http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlexception.aspx

找到的属性

您需要抓住SqlException而不是任何例外。

答案 3 :(得分:1)

记录异常时,记录整个事物是个好主意,尤其是 stacktrace 。堆栈跟踪是最重要的部分。如果您只是记录ex.ToString(),则不会丢弃该信息。

答案 4 :(得分:1)

尝试

catch (SqlException ex) { }代替catch (Exception ex) { }

查看有关SqlException的MSDN信息。

答案 5 :(得分:1)

我再一次很迟,但答案看起来都不适合我。 OP上下文是SMO。使用SMO,SqlException可以封装为ExecutionFailureException的内部异常。这就是为什么他在看InnerException

以下是我用于记录SqlException详细信息的解决方案(如果存在Logger为log4net ILog)。

Catch block:

catch (Exception ex)
{
    Logger.Error("Unhandled error", ex);
    LogSqlErrors(ex);
}

LogSqlErrors(注意最后一行,这是照顾内部异常的原因):

private static void LogSqlErrors(Exception ex)
{
    if (ex == null)
        return;

    var sqlEx = ex as SqlException;
    if (sqlEx != null && sqlEx.Errors != null && sqlEx.Errors.Count > 0)
    {
        var sqlErrs = new StringBuilder();
        sqlErrs.AppendFormat("SqlException contains {0} SQL error(s):", sqlEx.Errors.Count)
            .AppendLine();
        foreach (SqlError err in sqlEx.Errors)
        {
            sqlErrs.AppendLine("--------------------------------")
                .AppendFormat("Msg {0}, Level {1}, State {2}, Procedure '{4}', Line {5}",
                    err.Number, err.Class, err.State, err.Procedure, err.LineNumber)
                .AppendLine()
                .AppendLine(err.Message);
        }
        Logger.Warn(sqlErrs.ToString());
    }

    LogSqlErrors(ex.InnerException);
}

不幸的是,如果你的sql命令字符串包含许多批次(使用go分隔符,如SMO所支持的),这不会告诉你哪个sql批处理产生错误。 (错误行号是针对失败的批次计算的,不考虑先前批次的行数。)

我已经检查了ExecutionFailureException的构建方式(在SMO版本12上使用反编译器):它可以存储此信息,但事实并非如此。所以你只能猜测。

此外,如果您使用ContinueOnError选项,则会吞下错误(不会存储在任何地方)。好吧,如果SMO团队可以改进他们库中的异常处理,那就太好了。