2016-10-13 2 views
0

엔티티 프레임 워크 4는 응용 프로그램이 이미 구축되었으므로이 엔티티 프레임 워크 4를 다루고 있습니다.엔티티 프레임 워크 : 원자 트랜잭션 (데이터베이스 컨텍스트)

시나리오 : 동일한 트랜잭션이 여전히 올바른/검증 데이터 트랜잭션과 실행 때 DBTransaction 내 코드와 트랜잭션이 중반 방법으로 중단되고 롤백 번 (데이터베이스에 데이터를 삽입이) 다음에 다음 실행 구현 이전 예외를 제공하여 중단합니다. 롤백이 데이터베이스 컨텍스트에서 유효성 검사 메시지와 데이터를 SQL처럼 제거해야한다고 생각하기 때문에 이해하기가 어렵습니다. 참고 : 정적 DatabaseContext를 모두 사용하고 있습니다. (내가 시도)

public class TestClass 
{ 
    static SampleDataBaseEntities ctx = new SampleDataBaseEntities(); 

    public void SqlTransaction() 
    { 
     ctx.Connection.Open(); 
     using (DbTransaction transaction = ctx.Connection.BeginTransaction()) 
     { 
      try 
      { 
       Student std = new Student(); 
       std.first_name = "first"; 
       //std.last_name = "last"; (This is responsible for generating the exception) 
       AddTeacher(); 
       ctx.AcceptAllChanges(); 
       transaction.Commit(); 
      } 
      catch (Exception e) 
      { 
       transaction.Rollback(); 
      } 
      finally 
      { 
       ctx.Connection.Close(); 
      } 
     } 
    } 

    public void SqlTransaction2() 
    { 
     ctx.Connection.Open(); 
     using (DbTransaction transaction = ctx.Connection.BeginTransaction()) 
     { 
      try 
      { 
       Student std = new Student(); 
       std.first_name = "first"; 
       std.last_name = "last"; 
       AddTeacher(); 
       ctx.Students.AddObject(std); 
       ctx.SaveChanges(false); 
       transaction.Commit(); 
       ctx.AcceptAllChanges(); 
      } 
      catch (Exception e) 
      { 
       transaction.Rollback(); 
       transaction.Dispose(); 
       ctx.Connection.Close(); 
      } 
     } 
    } 

    public void AddTeacher() 
    { 
     Teacher t = new Teacher(); 
     t.first_name = "teacher_first"; 
     t.last_name = "teacher_last"; 
     t.school_name = "PUCIT"; 
     ctx.Teachers.AddObject(t); 
     ctx.SaveChanges(false); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     TestClass test = new TestClass(); 
     test.SqlTransaction(); 
     test.SqlTransaction2(); 
    } 
} 

솔루션 : SaveChanges를 사용 (거짓). SaveChanges (false) 및 ctx.AcceptAllChanges() 사용.

해결 방법 : 해결 방법은 DatabaseContext 개체를 인스턴스화하는 것입니다.

더 적절한 솔루션을 찾는 이유 인 컨텍스트를 인스턴스화하는 동안 복잡성 문제가 있습니다. 미리 감사드립니다.

+0

정적 DatabaseContext를 사용하지 마십시오. 필요에 따라 하나를 만듭니다. 또한 SQL 트랜잭션을 수동으로 처리 할 필요가 없습니다. – Maarten

+0

'컨텍스트를 다시 인스턴스화하는 복잡성 문제'는 무엇입니까? – Maarten

+0

정적 DbContext는 스레드로부터 안전하지 않으므로 사용하지 마십시오. 또한 항상'using' 문을 사용하면 어떤 일이 잘못되면 컨텍스트가 변경 내용을 롤백합니다. –

답변

0

"해결 방법은 DatabaseContext 개체를 인스턴스화하는 것입니다."

예이 작업은 다시 트랜잭션을 수행하는 데 적합합니다. 정적 데이터 컨텍스트를 사용하고 있으므로 다음 번에 트랜잭션을 수행 할 때 동일한 데이터 컨텍스트가 사용되어 데이터 입력 및 유효성 검사 오류가 다시 발생합니다.

솔루션 : 매우 빠른 트랜잭션을 수행 중이므로 정적 dataContext를 사용하지 마십시오. 따라서 각 트랜잭션마다 업데이트 된 datacontext가 필요합니다. 그래서 항상 새로운 dataContext를 인스턴스화하고 트랜잭션이 완료 되 자마자 폐기하도록하십시오. 희망!

+0

예! 컨텍스트의 정적 객체를 만들지 말라는 당신의 요지가 있습니다.컨텍스트 개체가 생성자에서 초기화되고 모든 응용 프로그램에서 사용됩니다. 원자 트랜잭션 시나리오에서 중간에 트랜잭션이 중단되면 컨텍스트 개체가 예외를 유지합니다. 다음 번에 해당 컨텍스트를 사용하려고하면 이전 예외가 표시됩니다. 왜 그렇게합니까? –

+0

이것은 "faulty"dataContext를 다시 사용하기 때문입니다. – Umar

+0

동일한 클래스 내에서 동일한 객체가 필요한 경우 왜 정적으로해야합니까? TestClass의 여러 객체를 만든 경우 동일한 더티 dataContext가 사용되기 때문에 문제가 발생할 것입니다. DataContext는 최소 수명을 가져야합니다. – Umar

2

모든 문제는 컨텍스트의 새 인스턴스를 만들지 않아 발생합니다. 이 코드를 단순화하면 제대로 작동합니다.

using (var ctx = new SampleDataBaseEntities()) { 
    Student std = new Student(); 
    std.first_name = "first"; 
    std.last_name = "last"; 
    ctx.Student.Add(std); 
    ctx.SaveChanges(); 
} 
관련 문제