최근 유지보수 업무 중 5개의 UPDATE 쿼리를 순차적으로 실행해야 하는 건이 있었다.
이 경우 중간에 오류가 발생하면 데이터 무결성이 깨질 수 있으므로 트랜잭션 처리가 필요하다고 생각했다.
회사 내 기존 코드를 살펴보니, 지금까지는 트랜잭션을 적용하지 않고 단순히 쿼리를 실행하는 방식만 사용하고 있었다.
따라서 이번 기회에 C#에서 트랜잭션을 처리하는 방법을 정리한다.
쿼리 내 테이블과 컬럼은 가칭이다.
public int UpdateId(string updateId, string originId) { SqlTransaction tran = null; string sql = string.Empty; try { con.Open(); tran = con.BeginTransaction(); //트랜잭션 시작 SqlCommand cmd = new SqlCommand(); cmd.Connection = con; cmd.Transaction = tran; cmd.Parameters.Add(new SqlParameter("UpdateId", updateId)); cmd.Parameters.Add(new SqlParameter("OriginId", originId)); sql = " UPDATE A SET a = @UpdateId WHERE b = @OriginId; "; cmd.CommandText = sSql; cmd.ExecuteNonQuery(); sql = " UPDATE B SET a = @UpdateId WHERE b = @OriginId; "; cmd.CommandText = sSql; cmd.ExecuteNonQuery(); sql = " UPDATE C SET a = @UpdateId WHERE b = @OriginId; "; cmd.CommandText = sSql; cmd.ExecuteNonQuery(); sql = " UPDATE D SET a = @UpdateId WHERE b = @OriginId; "; cmd.CommandText = sSql; cmd.ExecuteNonQuery(); sql = " UPDATE E SET a = @UpdateId WHERE b = @OriginId; "; cmd.CommandText = sSql; cmd.ExecuteNonQuery(); tran.Commit(); //모두 완료되면 커밋 con.Close(); return 1; } catch (Exception ex) { //로그 찍기 if (tran != null) { tran.Rollback(); //하나라도 실패 시 롤백 } return 0; } }
1) 트랜잭션 시작
tran = con.BeginTransaction(); //트랜잭션 시작
2) 파라미터 적용
SQL Injection 방지를 위해 파라미터를 적용하자.
문자열로 처리할 경우 사용자 입력 값에 공격문이 들어올 수 있으므로 미리 예방하자.
cmd.Parameters.Add(new SqlParameter("UpdateId", updateId)); cmd.Parameters.Add(new SqlParameter("OriginId", originId));
3) 커밋
쿼리를 모두 수행하면 커밋을 하자.
tran.Commit(); //모두 완료되면 커밋
4) 롤백 처리
처리 중 오류가 발생했을 경우 반드시 롤백을 하자.
롤백하지 않으면 트랜잭션을 사용하는 의미가 없다.
나 같은 경우 의도적으로 세 번째 쿼리에서 오류를 발생하여 롤백되는 과정을 테스트 하였다.
if (tran != null) { tran.Rollback(); //하나라도 실패 시 롤백 }
역시 어노테이션이면 다 되는 Spring Boot가 강자라는 것을 느꼈다.