2016-05-18 6 views
0

ユーザーがレコードを「更新」するたびに、データベーステーブルを1回のトランザクションで2回更新しようとしています。最初に、キャンセル日付を有効日付に設定して元のレコードを「キャンセル」します。次に、値を指定して新しいレコードを入力します。これは更新履歴を記録する方法です。データベースオブジェクトを適切に処分する方法と必要なクリーンアップについてのアドバイスを探します

私は、データベースオブジェクトを適切に処分する方法と、必要なクリーンアップについてのアドバイスを探しています。たとえば、私の「使用する」ブロックは合理的ですか?トランザクションが開始されたにもかかわらず、トランザクションが開始された後で何かがうまくいかない場合、暗黙のロールバックが発生すると想定できますか?彼らもさえ例外の中に、配置された取得するつもりだので

public void UpdateStateAssessment(Models.StateAssessment stateAssessment) 
    { 
     string updateSql = @"UPDATE GSAS.ST_ASSMT_REF 
          SET 
          CAN_DT  = EFF_DT 
          WHERE 
           VENDR_ID = @VENDR_ID AND 
           EFF_DT = @EFF_DT AND 
           LAST_TS = @LAST_TS"; 

     string insertSql = @"INSERT INTO GSAS.ST_ASSMT_REF 
         (
         VENDR_ID 
         ,ST_ASSMT_NM  
         ,ST_CD 
         ,EFF_DT 
         ,CAN_DT 
         ,LAST_TS  
         ,LAST_OPER_ID  
         ) 
         VALUES 
         (
         @VENDR_ID 
         ,@ST_ASSMT_NM 
         ,@ST_CD 
         ,@EFF_DT 
         ,@CAN_DT 
         ,CURRENT TIMESTAMP  
         ,@LAST_OPER_ID 
         )"; 

     try 
     { 
      using (var connection = OpenConnection()) 
      { 
       DB2Transaction sqltransaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); 

       using (sqltransaction) 
       { 
        using (DB2Command cmd = connection.CreateCommand()) 
        { 
         cmd.CommandText = updateSql; 
         cmd.CommandType = CommandType.Text; 
         cmd.Transaction = sqltransaction; 
         cmd.Connection = connection; 
         cmd.Parameters.Add(new DB2Parameter("@CAN_DT", DB2Type.Date) { Value = stateAssessment.CancelDate.Date }); 
         cmd.Parameters.Add(new DB2Parameter("@VENDR_ID", DB2Type.Char) { Value = stateAssessment.VendorId }); 
         cmd.Parameters.Add(new DB2Parameter("@EFF_DT", DB2Type.Date) { Value = stateAssessment.EffectiveDate.Date }); 
         cmd.Parameters.Add(new DB2Parameter("@LAST_TS", DB2Type.DateTime) { Value = stateAssessment.LastTimestamp }); 
         cmd.ExecuteNonQuery(); 
        } 

        using (DB2Command cmd = connection.CreateCommand()) 
        { 
         cmd.CommandText = insertSql; 
         cmd.CommandType = CommandType.Text; 
         cmd.Transaction = sqltransaction; 
         cmd.Connection = connection; 
         cmd.Parameters.Add(new DB2Parameter("@ST_ASSMT_NM", DB2Type.Char) { Value = stateAssessment.Name }); 
         cmd.Parameters.Add(new DB2Parameter("@ST_CD", DB2Type.Char) { Value = stateAssessment.StateCode }); 
         cmd.Parameters.Add(new DB2Parameter("@CAN_DT", DB2Type.Date) { Value = stateAssessment.CancelDate.Date }); 
         cmd.Parameters.Add(new DB2Parameter("@LAST_OPER_ID", DB2Type.Char) { Value = stateAssessment.LastOperatorId }); 
         cmd.Parameters.Add(new DB2Parameter("@VENDR_ID", DB2Type.Char) { Value = stateAssessment.VendorId }); 
         cmd.Parameters.Add(new DB2Parameter("@EFF_DT", DB2Type.Date) { Value = stateAssessment.EffectiveDate.Date }); 
         cmd.ExecuteNonQuery(); 
        } 

        sqltransaction.Commit(); 
       } 
      } 
     } 
     catch (Exception exception) 
     { 
      //Log the error. 
      //Any Cleaning up to do? 
     } 
    } 

答えて

1

あなたの使い捨てのオブジェクトがすべて正しくusingブロックに包まれています。

コマンドはトランザクションに含まれているため、トランザクションがコミットされるまでコミットされません。最初のコマンドは実行されますが、2番目のコマンドが例外をスローすると、トランザクションはコミットされません。

documentationは、コミットされていないトランザクションを明示的にロールバックするように指示します。

sqltransaction.Rollback(); 
+0

その後、私はそれが外側のブロックであると私はロールバックする前に、それがnullでないかどうかを確認する必要がありますのでのSqlTransactionオブジェクトの宣言を移動する必要があります。おそらく、ロールバックしようとする前に、トランザクションが開始されたかどうかを確認する方法もあります。だからこそ私は、使用ブロックがロールバックを処理することを望んでいたのです。 – ChadD

+0

このコマンドを使用する場合と同様に、usingステートメントでトランザクションを作成することもできます( 'use(var sqltransaction = connection.BeginTransaction(IsolationLevel.ReadCommitted))')。その後、try/catchを配置します。例外がスローされた場合は、トランザクションが範囲外になる前にロールバックします。 –

関連する問題