2015-01-20 6 views
1

여러 개의 .sQL 파일을 처리해야하는 시나리오가 있습니다. 모든 파일에 3-4 개의 삽입 또는 업데이트 쿼리가 포함되어 있습니다. 이제는 파일의 쿼리가 실패 할 때 rollback 전체 트랜잭션은 전체 파일을 의미합니다. 롤백해야하며 그 파일 이전에 실행 된 다른 모든 파일은 커밋됩니다. 나는 사용자가 rollback을 실행할 수있는 옵션을 원합니다. 전체 트랜잭션은 실행 된 파일의 모든 쿼리와 오류를 포함하는 특정 파일 이전에 실행 된 모든 파일을 의미하며 사용자가 건너 뛰기를 원할 경우 오류가있는 특정 파일 rollback 하나의 파일에 오류가있는 모든 파일이 커밋됩니다. 지금은 SQL 트랜잭션을 사용하고 있습니다. TransactionScope하지만 필요에 따라 TransactionScope()도 전환 할 수 있습니다. Curren 당신이 즉 부분적으로 더 큰 거래를 재개 한 후 롤백 할 수있는 옵션, SavePoints 찾고있는 것 같다자식 부모 트랜잭션 롤백

Var Files[] 
for each (string query in Files) 
{ 
    Execute(Query) 
IF(TRUE) 
CommitQuery() 
Else 
result=MBOX("IF You want to abort all files or skip this one") 
if(result=abort) 
rollbackall() 
else 
QueryRollBack() 
} 

답변

1

를 다음과 같이 내 코드에 대한 TLY 의사는 (내가 원하는)입니다. AFAIK TransactionScopedoesn't support SavePoints 네이티브 공급자 (예 :)와 직접 거래해야합니다 (RDBMS가 SQL Server 인 경우). (즉, 당신은 분산 데이터베이스, 서로 다른 RDBMS, 또는 병렬 거래를 통해 예 SavePointsDTC 상당을 구현하는 TransactionScope의 능력을 활용할 수 없습니다), I 사용자가 건너 뛰거나 앞을 중단하기로 결정한 전략을 제안했다

트랜잭션 처리가 시작되기 전에 많은 수의 행이 여전히 잠겨있는 동안 UI 응답을 기다리는 것이 비쌀 것이므로이 문제는 경쟁 문제를 일으킬 수 있습니다.

편집

여기 SavePoints을 사용하는 작은 샘플입니다. Foo1과 Foo3이 삽입되면 Foo2는 이전 저장 점으로 롤백됩니다.

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Foo"].ConnectionString)) 
{ 
    conn.Open(); 
    using (var txn = conn.BeginTransaction("Outer")) 
    { 
     txn.Save("BeforeFoo1"); 
     InsertFoo(txn, "Foo1"); 

     txn.Save("BeforeFoo2"); 
     InsertFoo(txn, "Foo2"); 
     txn.Rollback("BeforeFoo2"); 

     txn.Save("BeforeFoo3"); 
     InsertFoo(txn, "Foo3"); 
     txn.Commit(); 
    } 
} 

InsertFoo은 여기서

private void InsertFoo(SqlTransaction txn, string fooName) 
{ 
    using (var cmd = txn.Connection.CreateCommand()) 
    { 
     cmd.Transaction = txn; 
     cmd.CommandType = CommandType.Text; 
     cmd.CommandText = "INSERT INTO FOO(Name) VALUES(@Name)"; 
     cmd.Parameters.Add(new SqlParameter("@Name", SqlDbType.VarChar)).Value = fooName; 
     cmd.ExecuteNonQuery(); 
    } 
} 

그리고 기본 테이블은 다음과 같습니다 예외가 발생했을 경우

create table Foo 
(
    FooId INT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    Name NVARCHAR(50) 
) 
+0

덕분에, 내가 먼저 옵션을 고려하지만 난 90 + .SQL 파일이 모든 파일이 30 개 이상의 쿼리를 포함 불행하게도 나는, 내 UI – user1764351

+0

내가 죽일이 옵션에 갈 수 없습니다 만 사용자가 결정을 기다리는 동안 메시지 상자가 팝업 될 때마다 "외부"트랜잭션에 의해 잠긴 모든 행이 여전히 잠겨지고 예를 들어 다음과 같이 에스컬레이션된다는 점을 확인하고 싶었습니다. 테이블 잠금. 동시 액세스에는 좋지 않습니다. 동시 작업이있는 경우 전체 배치가 교착 상태의 피해자로 종료 될 위험이 있습니다. – StuartLC

+0

바로 그 이유는 사용자에게 메시지 상자를 표시하지 않는 옵션을 제공했기 때문입니다.이 경우 전체 프로세스가 사용자 중단없이 롤백되고 건너 뛰거나 시나리오를 중단하고 새로 작성한 코드를 실행하려고합니다. DB 그래서 아무데도 해당 DB에 대한 보류중인 트랜잭션이 없을 것입니다 (아무도 그 데이터베이스를 사용할 때까지 아무 것도하지 않습니다.) – user1764351

0

는 캐치 롤, 모든 삽입을 계속 업데이트 조회하는 try{..}catch(..){..}과 db 트랜잭션 다시. 그 제안에 대한

 private void InsertFoo(SqlTransaction txn, string fooName) 
    { 
     using (var cmd = txn.Connection.CreateCommand()) 
     { 
      try 
      { 
       do your process here... 
       cmd.Commit(); 
      } 
      catch(Exception ex) 
      { 
       cmd.Rollback(); 
      } 
     } 
    }