2011-03-07 2 views
3

Entity Framework 4를 사용하여 매우 간단한 데이터베이스를 만들었습니다. 엔티티에서 트랜잭션을 사용할 수 있기를 원하지만 변경 내용을 롤백하지 못하는 것 같습니다. 엔티티가 데이터베이스에 저장되기 전에 엔티티에 대한 임시 변경 사항을 포기하는 방법이 필요합니다.Entity Framework 개체 컨텍스트를 사용하여 트랜잭션을 수행하는 방법은 무엇입니까?

예를 들어, 다음 코드는 엔터티 프레임 워크 개체 컨텍스트 "MusicContainer"를 사용합니다. TransactionScope 내에서 아티스트 엔티티가 생성됩니다. 트랜잭션은 완료되지 않고 종료됩니다. 그래서 트랜잭션이 롤백되기를 기대합니다. 하지만, 처음에는 TransactionScope를 만들지 않은 것처럼 프로그램이 실행됩니다. TransactionScope가 끝나면 music.SaveChanges() 줄이 개체를 데이터베이스에 저장합니다. 엔티티 프레임 워크는 TransactionScope에에게 내가 여기에 기대하고있어 방법을 사용하지 않는 경우

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MusicContainer music = new MusicContainer()) 
     { 
      using (TransactionScope transaction = new TransactionScope()) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
      } 
      // The transaction ended without Complete(); shouldn't the changes be abandoned? 
      music.SaveChanges(); 
     } 
    } 
} 

, 어떻게 내가 찾는 기능을 얻을 수 있나요? 함수 호출자가 MusicContainer를 전달하는 몇 가지 상황이 있습니다. 함수에서 돌아 오기 전에 MusicContainer를 깨끗한 상태로 두어야합니다 (즉, 변경 사항을 롤백하여 우연히 다른 SaveChanges와 함께 저장되지 않도록합니다). 동일한 MusicContainer 개체에 있음).

답변

7

당신은 모든이 시나리오에 TransactionScope 필요하지 않습니다는 SaveChanges() 모든 것을이 필요한 - 당신은 MusicContainer와 다른 using 블록이있는 경우,이 별도의 트랜잭션에있을 것입니다 및 내 변경 내용을 저장하지 않습니다 현재 using 블록. TransactionScope은 여러 DB 컨텍스트에 걸친 트랜잭션에만 필요합니다.

일반적으로 컨텍스트는 관련 작업으로 구성된 작업 단위 (예 : 작업 완료 후 SaveChanges())로만 사용해야합니다. 서로 관련되지 않은 각각의 작업 단위에 대해 새로운 컨텍스트를 엽니 다. 그렇게 말하면, 당신의 시나리오에서 이것을 사용하십시오 :

+0

각 거래마다 별도의 "using (MusicContainer music = new MusicContainer())"를 사용 하시겠습니까? 첫 번째 의심은 병행으로 수십 개가 병목 현상이 될 경우 병목 현상이 될 수 있다는 것이 었습니다. –

+2

@notfed 오버 헤드가 거의 없다고 생각합니다. DB 연결은 필요할 때, 즉 SaveChanges()를 호출하거나 쿼리를 수행 할 때 EF에서만 사용됩니다.이 MSDN 기사도 확인하십시오. http://msdn.microsoft.com/ ko-kr/library/cc853327.aspx – BrokenGlass

+2

@notfed : 각 트랜잭션마다 새 컨테이너를 사용해야합니다. 읽기 : http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392 –

2

잘못된 저장 위치가 있습니다.

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MusicContainer music = new MusicContainer()) 
     { 
      using (TransactionScope transaction = new TransactionScope()) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
       music.SaveChanges(); 
      } 
      // The transaction ended without Complete(); the changes are abandoned? 
     } 
    } 
} 

당신은 당신이 트랜잭션이 실패 MusicContainer 경우 다시 사용해서는 안된다. 각 Unit of Work

+0

나는 목적에 따라 틀린 장소에 SaveChanges를 가지고 있습니다. 내 요점은 : 내가 준 코드에서 SaveChanges가 이러한 변경 사항을 저장하는 이유는 무엇입니까? –

+1

MusicContainer 앞에 TransactionScope를 선언해야합니다. – edze

0

엔티티 프레임 워크에 대한 새로운 하나를 만들기 TransactionScope에을 사용할 수 있어야합니다. 이 방법으로 만 적용된 변경 사항을 롤백해야하는 경우 새 TransactionScope를 시작해야합니다.

using (MusicContainer music = new MusicContainer()) 
    { 
    using (TransactionScope transaction = new TransactionScope(TransactionScopeOptions.RequiresNew)) 
      { 
       Artist artist = new Artist { Name = "Test" }; 
       music.Artists.AddObject(artist); 
       music.SaveChanges(); 
       scope.Complete(); 
      } 
    } 
+0

음, 호출자 함수에서 MusicContainer가 전달되는 경우, 나는 TransactionScope 내에 MusicContainer를 생성하는 옵션을 가지고 있지 않습니다. –

+0

그런 다음 메서드에서 SaveChanges를 호출 할 필요가 없습니다. 최상위 함수가 SaveChanges를 호출하도록하십시오. – Amitabh

+0

하지만 객체 컨텍스트에 대한 변경 사항을 _abandon_ 변경해야하며 호출자가 변경 내용을 저장하지 못하게해야합니다. –

관련 문제