web-dev-qa-db-ja.com

ExecuteNonQuery()の使用時に発生するエラーメッセージを取得するにはどうすればよいですか?

私はこのようにコマンドを実行しています:

var Command = new SqlCommand(cmdText, Connection, tr);

Command.ExecuteNonQuery();

コマンドにはエラーがありますが、.NETはエラーメッセージをスローしません。コマンドが正しく実行されなかったこと、および例外を取得するにはどうすればよいですか?

18

エラーの重大度が16以上の場合にのみ、C#で例外が発生します。 PRINTを使用している場合、.NETで例外は発生しません。

エラーの発生コードを編集できる場合、これによりC#でSqlExceptionが発生します。

RAISERROR('Some error message', 16, 1)

その後、SqlException.Errorsコレクションの個々のエラーにアクセスできます。

余談ですが、SQL Serverは、直接RAISERRORを実行しない場合、RETURNの後にコマンドを実行し続けます。戻らない場合、複数のエラーが返される可能性があります。

14
Kevin McKelvin

.NETは確かにエラーメッセージを表示します...if重大度が16以上(例外をスローするため)-メッセージは例外.Message。重要度の低いRAISERRORを使用している場合(またはPRINTを使用している場合)、接続で InfoMessageイベント をサブスクライブする必要があります。

17
Marc Gravell

重大度の高いエラーのみがExecuteNonQueryでスローされます。 OdbcCommand.ExecuteNonQuery()メソッドで観察した別のシナリオがあります。 SqlCommand.ExecuteNonQuery()についても同様です。 CommandTextプロパティに含まれるSQLが単一のステートメント(例:INSERT INTO table(col1、col2)VALUES(2、 'ABC');)であり、上記のステートメントExecuteNonQueryに外部キー違反または主キー違反がある場合例外をスローします。ただし、CommandTextがセミコロンで区切られた複数のSQLステートメント(複数のINSERTSまたはUPDATESなど)のバッチであり、それらの1つが失敗した場合、ExecuteNonQueryは例外をスローしません。メソッドによって返された、影響を受けるレコードの数を明示的にチェックする必要があります。コードをtry {} Catch {}に置くだけでは効果がありません。

1

以下をお試しください。

PS:トランザクションを使用するからといって、例外とロールバックの処理を無視できるという意味ではありません。

 public static void MessageEventHandler( object sender, SqlInfoMessageEventArgs e ) {
         foreach( SqlError error in e.Errors ) {
            Console.WriteLine("problem with sql: "+error);
            throw new Exception("problem with sql: "+error);
         }
      }
      public static int executeSQLUpdate(string database, string command) {
         SqlConnection connection = null;
         SqlCommand sqlcommand = null;
         int rows = -1;
         try {
            connection = getConnection(database);
            connection.InfoMessage += new SqlInfoMessageEventHandler( MessageEventHandler );
            sqlcommand = connection.CreateCommand();
            sqlcommand.CommandText = command;
            connection.Open();
            rows = sqlcommand.ExecuteNonQuery();
          } catch(Exception e) {
            Console.Write("executeSQLUpdate: problem with command:"+command+"e="+e);
            Console.Out.Flush();
            throw new Exception("executeSQLUpdate: problem with command:"+command,e);
         } finally {
            if(connection != null) { connection.Close(); }
         } 
         return rows;
      }

そしてこれは適切なトランザクション処理です:

//public static void ExecuteInTransaction(Subtext.Scripting.SqlScriptRunner srScriptRunner)
        public override void ExecuteInTransaction(string strSQL)
        {

            System.Data.Odbc.OdbcTransaction trnTransaction = null;

            try
            {


                System.Threading.Monitor.Enter(m_SqlConnection);
                if (isDataBaseConnectionOpen() == false)
                    OpenSQLConnection();

                trnTransaction = m_SqlConnection.BeginTransaction();

                try
                {
                    /*
                    foreach (Subtext.Scripting.Script scThisScript in srScriptRunner.ScriptCollection)
                    {
                        System.Data.Odbc.OdbcCommand cmd = new System.Data.Odbc.OdbcCommand(scThisScript.ScriptText, m_sqlConnection, trnTransaction);
                        cmd.ExecuteNonQuery();
                    }
                    */

                    // pfff, mono C# compiler problem...
                    // System.Data.Odbc.OdbcCommand cmd = new System.Data.Odbc.OdbcCommand(strSQL, m_SqlConnection, trnTransaction);
                    System.Data.Odbc.OdbcCommand cmd = this.m_SqlConnection.CreateCommand();
                    cmd.CommandText = strSQL;

                    cmd.ExecuteNonQuery();

                    trnTransaction.Commit();
                } // End Try
                catch (System.Data.Odbc.OdbcException exSQLerror)
                {
                    Log(strSQL);
                    Log(exSQLerror.Message);
                    Log(exSQLerror.StackTrace);
                    trnTransaction.Rollback();
                } // End Catch
            } // End Try
            catch (Exception ex)
            {
                Log(strSQL);
                Log(ex.Message);
                Log(ex.StackTrace);
            } // End Catch
            finally
            {
                strSQL = null;
                if(m_SqlConnection.State != System.Data.ConnectionState.Closed)
                    m_SqlConnection.Close();
                System.Threading.Monitor.Exit(m_SqlConnection);
            } // End Finally


        } // End Sub ExecuteInTransaction
0
Stefan Steiger

このスレッドでのM Hassan、Stefan Steiger、およびMark Gravellの作業に触発されて、ここで行われていることの概念実証の最小限の例を示します。

private static void DoSql()
{
    // Errors of severity level of 10 or less 
    // will NOT bubble up to .Net as an Exception to be caught in the usual way
    const string sql = @"RAISERROR('A test error message of low severity', 10, 1)";

    using (SqlConnection conn = new SqlConnection(myConnString))
    {
        conn.Open();

        // Hook up my listener to the connection message generator
        conn.InfoMessage += new SqlInfoMessageEventHandler(MySqlMessageHandler);

        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            cmd.ExecuteNonQuery();
            // code happily carries on to this point
            // despite the sql Level 10 error that happened above
        }
    }
}


private static void MySqlMessageHandler(object sender, SqlInfoMessageEventArgs e)
{
    // This gets all the messages generated during the execution of the SQL, 
    // including low-severity error messages.
    foreach (SqlError err in e.Errors)
    {
        // TODO: Something smarter than this for handling the messages
        MessageBox.Show(err.Message);
    }
}
0
Jinlye

これは、Oracle ODP.Netを使用したWCFサービスでうまく機能することがわかりました-

            try
            {
                cmd.Connection = conn;
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (OracleException oex)
            {
                string errmsg = oex.Message;
                Logger.Instance.WriteLog(@"Some error --> " + errmsg);
                throw new Exception(errmsg);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cleanup...
            }
0
Frank Silano