2011-03-02 2 views
2

일부 비즈니스 사례에서 내 앱에 트랜잭션 오류가 발생합니다. 상황은 다음과 같습니다'SubmitChanges'가 실패했지만 다른 제출이 필요한 경우 DBContext에서 데이터 변경 사항을 롤백하는 방법은 무엇입니까?

static void MyFunc(DBContext context) 
{ 
    context.MyObjects.InsertOnSubmit(new MyObj{Id=1}); 
             // Id - is a primary key 
    context.MyObjects.InsertOnSubmit(new MyObj{Id=1}); 
             // here I force system to fail 
             // by trying to add record with 
             // duplicated primary key value 

    context.SubmitChanges(); // causes an error (as expected) 
} 

static void main() 
{ 
    using (DBContext context = new DBContext()) 
    { 
     try 
     { 
      using (TransactionScope scope = CreateTransactionScope()) 
      { 
       MyFunc(context); 

       scope.Complete(); 
      } 
     } 
     catch(Exception exc) 
     { 
      MyLog log = new MyLog{...valid object data... want to log error ... }; 
      context.MyLogs.InsertOnSubmit(log); 
      context.SubmitChanges(); 
     } 
    } 
} 

여기에 문제가 저장 '로그인'할 것을 시도 오브젝트가 너무 '을 MyObject'테이블에 이전에 추가 된 객체를 저장하는 시도가 발생합니다! 결과적으로 로그 레코드를 저장할 수 없으며 ... 'main'함수가 예외를 throw합니다.

어떻게 해결할 수 있습니까? 어떤 생각이라도 환영합니다.

(나는 MS SQL 2005을 사용하고, Linq2Sql는 .NET 3.5, .NET 4.0에 대한 아이디어도 환영!)

P.S. 'scope.Rollback'을 호출하는 것이 좋을지 모르겠지만 'Complete'를 호출하지 않고 'TransactionScope scope ...'를 사용하면 'Rollback이 자동으로 적용되어야합니다.'... '

P.P.S. 새로운 'DBContext'객체를 만들 수는 있지만 합리적이라고 생각하지는 않습니다.

+1

별도의 컨텍스트하지 합리적인 솔루션과 같은 맥락에서 롤백 할 수 있습니까? –

+0

다른 방법이 있다면 - 나는 그것을 선호한다. 그렇지 않다면 - 해결책이 될 것이다. 문제는 다음과 같다 : 비즈니스 로직이 SubmitChanges 동안 오류를 일으킬 수 있지만 다른 변경 사항은 나중에 발생할 것으로 예상한다. (같은 맥락에서) 같은 호출에서 수행되어야 할 필요가있을 것입니다 ... 그리고 컨텍스트를 가지고 노는 것은 저에게 매우 매력적이지 않습니다. – Budda

+0

나머지 데이터가 기록되지 않아도 데이터를 기록하려면 두 가지 간단한 선택이 있습니다. 1) 별도의 컨텍스트를 사용하고, 2) 별도의 트랜잭션을 사용하십시오. –

답변

4

트랜잭션은 부분이 아닌 전체적으로 수행해야하는 작업을 그룹화하는 도구입니다. 나머지 작업과 쉽게 분리 할 수있는 몇 가지 작업이 있으므로 두 가지 별도의 트랜잭션을 사용하는 것이 더 적절합니다.

+0

다시 한번 : 감사합니다. – Budda

1

일반적으로 DataContext는 메모리에서로드되거나 메모리에로드 된 모든 개체에 대한 참조를 유지합니다. 틀릴 수도 있지만, TransactionScope의 변경 사항이 "메모리 내"개체에서 롤백되는 것을 믿지 않습니다.

따라서 오류 처리기의 컨텍스트에 대한 SubmitChanges()는 "메모리 내"모델에 대한 모든 변경 사항을 다시 제출하려고 시도합니다. 이 문제를 해결하는 유일한 방법은 새로운 컨텍스트를 만들어 "메모리 내"모델을 다시 설정하는 것입니다.

2

이 왜 만드는

public void Rollback() 
{ 
    base.ChangeTracker.Entries().ToList().ForEach(entry => entry.State = System.Data.EntityState.Unchanged); 
} 
+0

하지만 메모리 내 개체를 현재 데이터베이스 개체에 적용하는 것은 아닙니다. 나중에 DbContext와 해당 개체의 수명 기간 동안 다른 속성을 수정 한 경우 다른 속성이 더러워 져서 변경 내용 검색 설정에 따라 데이터베이스에 다시 저장 될 수도 있습니다. – mlhDev

+0

롤백이 아니므로 변경 사항이 지속되지 않습니다. –

관련 문제