문제

나는 거래를 조사 해 왔으며 통과하는 한 그들이 EF에서 스스로 돌보는 것으로 보입니다. false 에게 SaveChanges() 그런 다음 전화하십시오 AcceptAllChanges() 오류가없는 경우 :

SaveChanges(false);
// ...
AcceptAllChanges();

뭔가 나빠지면 어떨까요? 롤백해야 할 필요가 없거나 내 메소드가 범위를 벗어나 자마자 거래가 종료 되었습니까?

거래를 통해 반쯤 할당 된 계약은 어떻게됩니까? 나는 다른 사람이 내 후에 내 후에 기록을 추가하면 나쁘게되기 전에 기록을 추가 한 경우, 이것은 신원 가치가 누락 될 것임을 의미합니다.

표준을 사용할 이유가 있습니까? TransactionScope 내 코드의 수업?

도움이 되었습니까?

해결책

엔티티 프레임 워크와 함께 대부분 SaveChanges() 충분하다. 이는 거래를 생성하거나 주변 거래에 입대하며 해당 거래에서 필요한 모든 작업을 수행합니다.

때로는 SaveChanges(false) + AcceptAllChanges() 페어링이 유용합니다.

이를위한 가장 유용한 장소는 두 가지 다른 맥락에서 분산 거래를 수행하려는 상황입니다.

즉, 이와 같은 것 (나쁜) :

using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save and discard changes
    context1.SaveChanges();

    //Save and discard changes
    context2.SaveChanges();

    //if we get here things are looking good.
    scope.Complete();
}

만약에 context1.SaveChanges() 성공하지만 성공합니다 context2.SaveChanges() 전체 분산 트랜잭션이 중단됩니다. 그러나 불행히도 엔티티 프레임 워크는 이미 변경 사항을 폐기했습니다. context1, 실패를 재생하거나 효과적으로 기록 할 수 없습니다.

그러나 코드를 다음과 같이 보이게하는 경우 :

using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save Changes but don't discard yet
    context1.SaveChanges(false);

    //Save Changes but don't discard yet
    context2.SaveChanges(false);

    //if we get here things are looking good.
    scope.Complete();
    context1.AcceptAllChanges();
    context2.AcceptAllChanges();

}

전화하는 동안 SaveChanges(false) 필요한 명령을 데이터베이스에 보내면 컨텍스트 자체가 변경되지 않으므로 필요한 경우 다시 수행 할 수 있습니다. 그렇지 않으면 심문 할 수 있습니다. ObjectStateManager 네가 원한다면.

즉, 트랜잭션이 실제로 예외를 던지면 각 상황의 상태를 다시 사용하거나 로깅하여 보상 할 수 있습니다. ObjectStateManager 어딘가에.

보다 나의 블로그 게시물 이상.

다른 팁

EF6 (Entity Framework 6+)을 사용하는 경우 데이터베이스 호출이 SQL로 변경되었습니다.
보다: http://msdn.microsoft.com/en-us/data/dn456843.aspx

context.database.begintransaction을 사용하십시오.

MSDN에서 :

using (var context = new BloggingContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
        try 
        { 
            context.Database.ExecuteSqlCommand( 
                @"UPDATE Blogs SET Rating = 5" + 
                    " WHERE Name LIKE '%Entity Framework%'" 
                ); 

            var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
            foreach (var post in query) 
            { 
                post.Title += "[Cool Blog]"; 
            } 

            context.SaveChanges(); 

            dbContextTransaction.Commit(); 
        } 
        catch (Exception) 
        { 
            dbContextTransaction.Rollback(); //Required according to MSDN article 
            throw; //Not in MSDN article, but recommended so the exception still bubbles up
        } 
    } 
} 

일부 데이터베이스는 dbcontextTransaction.commit ()에서 예외를 던질 수 있기 때문에 :

using (var context = new BloggingContext()) 
{ 
  using (var dbContextTransaction = context.Database.BeginTransaction()) 
  { 
    try 
    { 
      context.Database.ExecuteSqlCommand( 
          @"UPDATE Blogs SET Rating = 5" + 
              " WHERE Name LIKE '%Entity Framework%'" 
          ); 

      var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
      foreach (var post in query) 
      { 
          post.Title += "[Cool Blog]"; 
      } 

      context.SaveChanges(false); 

      dbContextTransaction.Commit(); 

      context.AcceptAllChanges();
    } 
    catch (Exception) 
    { 
      dbContextTransaction.Rollback(); 
    } 
  } 
} 
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top