복붙노트

[SQL] 어떻게 ExecuteNonQuery는 ()를 사용할 때 발생하는 오류 메시지를받을 수 있나요?

SQL

어떻게 ExecuteNonQuery는 ()를 사용할 때 발생하는 오류 메시지를받을 수 있나요?

나는이 방법으로 명령을 실행하고 있습니다 :

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

Command.ExecuteNonQuery();

명령에서 그러나 .NET이 오류 메시지가 발생하지 않는 오류가있다. 어떻게하면 명령이 제대로 실행되지 않았 음을 알 수 있고, 어떻게 예외를 얻을?

해결법

  1. ==============================

    1.당신의 오류의 심각도가 16 이상인 경우에만 C #에서 예외를 얻을 것이다. 당신이 PRINT를 사용하는 경우 .NET에서 예외가되지 않습니다.

    당신의 오류의 심각도가 16 이상인 경우에만 C #에서 예외를 얻을 것이다. 당신이 PRINT를 사용하는 경우 .NET에서 예외가되지 않습니다.

    당신이 인상 오류 코드를 편집 할 수 있다면, 이것은 C #에서 SQLEXCEPTION를 일으킬 것입니다 :

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

    그런 다음 SqlException.Errors 컬렉션에서 각 오류로 얻을 수 있습니다.

    그냥 사이드 노트 - SQL Server가 나중에 직접 반환하지 않는 경우 RAISERROR 후 명령을 계속 실행됩니다. 당신은 반환하지 않는 경우 여러 오류 등을 얻을 수 있습니다.

  2. ==============================

    2.(예외를 throw 때문에) 심각도가 16 이상인 경우 .NET 참 ... 오류 메시지가 인상 않습니다 - 메시지는 예외 .Message에있을 것입니다. 더 낮은 심각도로 RAISERROR를 사용하여 (또는 PRINT 사용)하는 경우에 당신은 연결에 InfoMessage 이벤트에 가입해야합니다.

    (예외를 throw 때문에) 심각도가 16 이상인 경우 .NET 참 ... 오류 메시지가 인상 않습니다 - 메시지는 예외 .Message에있을 것입니다. 더 낮은 심각도로 RAISERROR를 사용하여 (또는 PRINT 사용)하는 경우에 당신은 연결에 InfoMessage 이벤트에 가입해야합니다.

  3. ==============================

    3.만 심각도가 높은 오류는 ExecuteNonQuery는 다시 발생합니다. 내가 OdbcCommand.ExecuteNonQuery () 메소드를 관찰 한 또 다른 시나리오가있다. 이뿐만 아니라 SqlCommand.ExecuteNonQuery ()도 마찬가지입니다 수 있습니다. 는 SQL이 CommandText 속성에 포함 된 경우 하나의 명령문 (예 : INSERT INTO 테이블 (COL1, COL2) VALUES (2, 'ABC');)과 위의 문 ExecuteNonQuery는에서 외래 키 위반 또는 기본 키 위반이있는 경우 예외가 발생합니다. 그러나 귀하의 CommandText 당신이 (여러 인서트 나 업데이트 등) 세미 콜론으로 구분 된 하나 이상의 SQL 문이 있고 그 중 하나가 실패 할 경우 ExecuteNonQuery는 예외를 다시 throw하지 않습니다 배치됩니다. 명시 적 방법에 의해 반환 영향을받는 레코드 수를 확인해야합니다. 단순히 시도 {} 잡기 {} 늘 도움의 코드를 넣어.

    만 심각도가 높은 오류는 ExecuteNonQuery는 다시 발생합니다. 내가 OdbcCommand.ExecuteNonQuery () 메소드를 관찰 한 또 다른 시나리오가있다. 이뿐만 아니라 SqlCommand.ExecuteNonQuery ()도 마찬가지입니다 수 있습니다. 는 SQL이 CommandText 속성에 포함 된 경우 하나의 명령문 (예 : INSERT INTO 테이블 (COL1, COL2) VALUES (2, 'ABC');)과 위의 문 ExecuteNonQuery는에서 외래 키 위반 또는 기본 키 위반이있는 경우 예외가 발생합니다. 그러나 귀하의 CommandText 당신이 (여러 인서트 나 업데이트 등) 세미 콜론으로 구분 된 하나 이상의 SQL 문이 있고 그 중 하나가 실패 할 경우 ExecuteNonQuery는 예외를 다시 throw하지 않습니다 배치됩니다. 명시 적 방법에 의해 반환 영향을받는 레코드 수를 확인해야합니다. 단순히 시도 {} 잡기 {} 늘 도움의 코드를 넣어.

  4. ==============================

    4.이 스레드에서 M 하산, 스테판 스타 이거, 마크 Gravell의 작품에서 영감을, 여기 여기 무슨 일이 일어나고 있는지의 최소 개념 증명 예입니다 :

    이 스레드에서 M 하산, 스테판 스타 이거, 마크 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);
        }
    }
    
  5. ==============================

    5.나는 이것이 오라클 ODP.Net와 WCF 서비스에서 나를 위해 잘 작동하는 것으로 확인 -

    나는 이것이 오라클 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...
                }
    
  6. ==============================

    6.아래를보십시오.

    아래를보십시오.

    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
    
  7. ==============================

    7.당신은 시도 / 캐치를 사용하여 SQLEXCEPTION를 잡을

    당신은 시도 / 캐치를 사용하여 SQLEXCEPTION를 잡을

     try
      {
           //.......
        Command.ExecuteNonQuery();      
       }
        catch (SqlException ex)
         {   
           log (SqlExceptionMessage(ex).ToString());
         }
    

    로그인 또는 사용자에게 표시 할 수 SQLException의 다음과 같은 방법 캐치 세부 사항

      public StringBuilder SqlExceptionMessage(SqlException ex)
        {
            StringBuilder sqlErrorMessages = new StringBuilder("Sql Exception:\n");
    
            foreach (SqlError error in ex.Errors)
            {
                sqlErrorMessages.AppendFormat("Mesage: {0}\n", error.Message)
                    .AppendFormat("Severity level: {0}\n", error.Class)
                    .AppendFormat("State: {0}\n", error.State)
                    .AppendFormat("Number: {0}\n", error.Number)
                    .AppendFormat("Procedure: {0}\n", error.Procedure)
                    .AppendFormat("Source: {0}\n", error.Source)
                    .AppendFormat("LineNumber: {0}\n", error.LineNumber)
                    .AppendFormat("Server: {0}\n", error.Server)
                    .AppendLine(new string('-',error.Message.Length+7));
    
            }
            return sqlErrorMessages;
        }
    

    생성 된 메시지보기와 같은 :

     Sql Exception:
     Mesage: Error converting data type nvarchar to datetime.
     Severity level: 16
     State: 5
     Number: 8114
     Procedure: Sales by Year
     Source: .Net SqlClient Data Provider
     LineNumber: 0
     Server: myserver
     -------------------------------------------------------
    
  8. from https://stackoverflow.com/questions/7024109/how-can-i-get-an-error-message-that-happens-when-using-executenonquery by cc-by-sa and MIT license