2016-05-18 17 views
0

我试图在用户“更新”记录时在单个事务中对数据库表执行两次更新。首先,我通过将取消日期设置为生效日期来“取消”原始记录。然后,我输入提供的值的新记录。这是我们如何记录更新历史。寻找关于如何正确处置数据库对象和可能需要清理的建议

我正在寻找关于如何正确处置数据库对象以及可能需要清理的建议。例如,我的“使用”块是否合理?我可以假设,如果一个事务开始,但是在事务开始后的任何地方出现错误,那么隐含的回滚会发生?

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块,他们会得到处置,甚至在连一个例外。

由于命令包含在事务中,所以在事务提交之前它们不会被提交。如果第一个命令执行但第二个引发异常,那么事务不会被提交。

documentation表示如果未提交,则显式回滚事务。

sqltransaction.Rollback(); 
+0

然后,我需要移动sqltransaction对象的声明,以便它在外部块中,我必须检查它是否为空之前我回滚。在我试图回滚之前,也许还有一种方法可以检查交易是否已经开始......?这就是为什么我希望使用块也处理回滚。 – ChadD

+0

你可以在using语句中使用(var sqltransaction = connection.BeginTransaction(IsolationLevel.ReadCommitted))来创建事务 - 就像你对命令做的一样。然后在那里,尝试一下。如果抛出异常,请在事务超出范围之前回滚该事务。 –

相关问题