2016-12-30 12 views
1

트랜잭션에서 여러 테이블의 특정 작업 수가 발생하는지 확인해야하는 서비스 계층을 구현하고 있습니다. 다음은 작업 흐름입니다.DbContext가 아직 저장되지 않은 삽입 된 레코드에 대한 가시성을 얻는 방법

  1. HistoricalData 테이블에 저장해야하는 HistoricalData 개체의 인스턴스를 가져옵니다. 이것은 AddHistoricalData 메소드에서 수행됩니다.
  2. # 1에 삽입되었지만 더 많은 레코드가있을 수있는 HistoricalData 테이블의 모든 레코드를 검색해야합니다. 이 작업은 ProcessAllData 메서드에서 수행됩니다.
  3. 모든 레코드를 처리 한 결과는 두 개의 다른 테이블 인 ProcessStatus와 ProcessResults에 저장됩니다. 문제가 발생하면 작업 # 1에 삽입 된 내용을 롤백해야합니다.

이것은 구현 된 방법입니다.

public class HistoricalDataService : IHistoricalDataService 
    { 
     private MyDbContext dbContext; 
     public HistoricalDataService(MyDbContext context) 
     { 
      this.dbContext = context; 
     } 

     void AddHistoricalData(HistoricalData hData) 
     { 
      // insert into HistoricalData table 
     } 

     void ProcessAllData() 
     { 
      // Here we process all records from HistoricalData table insert porcessing results into two other tables 
     } 

     void SaveData() 
     { 
      this.dbContext.SaveChanges(); 
     } 
    } 

다음은이 클래스 메소드가 호출 된 방법입니다. 이 방법

HistoricalDataService service = new HistoricalDataService (dbcontext); 
service.AddHistoricalData(HistoricalData instance); 
service.ProcessAllData(); 
service.SaveData(); 

문제 AddHistoricalData 메소드를 호출하는 동안 HistoricalData 테이블에 삽입 어떤 dbContext.SaveChanges 만 끝에서 호출되기 때문에, ProcessAllData 전화에 표시되지 않는 것입니다. 어떻게 든 여기에 트랜잭션 범위를 가져올 필요가 있다고 생각하지만 그 트랜잭션 범위를 시작해야하는 함수를 공개하는 방법을 모르십니까?

+0

왜 HistoricalData가 보이지 않는다고합니까? HistoricalData 개체를 dbContext.HistoricalData에 삽입하면 ProcessAllData 메서드에서이 개체를 가져올 수 있습니다. – taquion

+0

이유는 모르지만 context.HistoricalData를 사용하여 AddHistoricalData 메서드에 삽입 된 위치를 알 수 없습니다.Add는 context.HistoricalData 컬렉션의 ProcessAllData Method에 표시됩니다. 내 생각 엔 컨텍스트에서 SaveChanges를 호출해야한다는 것입니다. –

답변

2

이렇게하는 방법에는 여러 가지가 있습니다. 등이 (테스트되지 않은,하지만 POC)

public class HistoricalDataService : IHistoricalDataService 
{ 
    private DbContext dbContext; 
    private DbContextTransaction dbContextTransaction; 

    public HistoricalDataService(DbContext context) 
    { 
     this.dbContext = context; 
    } 

    void AddHistoricalData(HistoricalData hData) 
    { 
     if (dbContext.Database.CurrentTransaction == null) 
     { 
      dbContextTransaction = dbContext.Database.BeginTransaction(); 
     } 

     // insert into HistoricalData table 
     dbContext.SaveChanges(); 
    } 

    void ProcessAllData() 
    { 
     // Here we process all records from HistoricalData table insert porcessing results into two other tables 
    } 

    void Rollback() 
    { 
     if (dbContextTransaction != null) 
     { 
      this.dbContextTransaction.Rollback(); 
     } 
    } 

    void SaveData() 
    { 
     this.dbContextTransaction.Commit(); 
     this.dbContextTransaction.Dispose(); 
    } 
} 

사용을 시도해보십시오

HistoricalDataService service = new HistoricalDataService (dbcontext); 

try 
{ 
    service.AddHistoricalData(HistoricalData instance); 
    service.ProcessAllData(); 
    service.SaveData(); 
} 
catch (Exception ex) 
{ 
    service.Rollback(); 
} 
0

나는 서비스가 하나의 (높은 수준의 추상화에서) 방법 및을 가질 수 있도록 코드를 리팩토링 추천 단일 책임 : 유스 케이스 처리.

후, 클라이언트 클래스는 서비스 클래스가 원시 ADO를 사용하는 경우 모든 작업은 트랜잭션 범위 중 하나와 함께 포장, 하나의 메소드 내에서 발생이 확인

private readonly IHistoricalDataService _historicalDataService; 

_historicalDataService.RearrangeSeatingArrangement(); //High level abstraction 

을 위하고의 목적입니다 것 EF를 사용하는 경우 .NET 또는 컨텍스트 개체. 하나만 호출 할 수있을 때 클라이언트 클래스에서 세 가지 메서드를 호출하지 마십시오. 이것은 우선 서비스 클래스의 목적입니다. 사용 사례를 처리하고 클라이언트 클래스 (아마도 귀하의 경우에는 컨트롤러)에 대한 응답을 반환합니다.

이제 코드의 일부가 지속 된 데이터를 인식하는지 확인하기 위해 몇 가지 추가 질문이 제기됩니다. 위에서 ProcessAllData() 동안 발생하는 명령, 왜 데이터를 정확히 분할합니까? ? 분할 된 데이터를 다른 도메인 클래스의 메모리로 분할하고 컨텍스트에 추가하고 SaveChanges() 메서드에 저장할 수 있습니까? 이렇게하면 데이터베이스에 한 번만 호출 할 수 있습니다 (Entity Framework 단위 작업의 목적 : 컨텍스트에서 변경 사항 누적, 추가, 삭제, 누락, 한 번의 조작으로 데이터베이스와의 대화).