2016-12-30 18 views
1

Я реализую сервисный уровень, где мне нужно убедиться, что в транзакции происходит определенное количество операций по нескольким таблицам. Вот работа.Как получить видимость для вставленных записей, где DbContext еще не сохранен

  1. Я получаю экземпляр объекта HistoricalData, который необходимо сохранить в таблице HistoricalData. Это выполняется в методе AddHistoricalData.
  2. Мне нужно получить все записи из таблицы HistoricalData, которые включают в себя то, что вставлено в # 1, но могут иметь больше записей. Это делается в методе 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(); 

Проблема такого подхода заключается в том, что все, что вставляется в HistoricalData таблицы во время вызова метода AddHistoricalData не видно в вызове ProcessAllData, поскольку dbContext.SaveChanges вызывается только в конце. Я думаю, что мне нужно каким-то образом включить область транзакций, но не уверен, как выставить функцию, в которой должна быть запущена эта область транзакций?

+0

Почему вы говорите, что HistoricalData не виден? если вы вставляете объекты HistoricalData в dbContext.HistoricalData, то вы должны иметь возможность получить эти объекты в методе ProcessAllData – taquion

+0

Не знаете, почему, но где был вставлен в метод AddHistoricalData с использованием context.HistoricalData.Добавить просто видно в ProcessAllData Method в контексте. Коллекция HistoricalData. Я предполагаю, что мне нужно вызвать 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

Я бы рекомендовал рефакторинга кода, так что служба имеет один метод (на более высоком уровне абстракции) и А единая ответственность: обращение использование кейс.

тогда, класс клиент будет иметь

private readonly IHistoricalDataService _historicalDataService; 

_historicalDataService.RearrangeSeatingArrangement(); //High level abstraction 

цель делает выше, чтобы обеспечить ваш класс услуг, все операции происходят в рамках одного метода, завернутые либо областью сделки, если используется сырой ADO .NET или объект контекста при использовании EF. Не нужно, чтобы класс клиента вызывал три метода, когда он мог просто вызвать ОДИН. В первую очередь это цель класса сервиса: обрабатывать варианты использования и возвращать ответ на класс клиента (возможно, контроллер в вашем случае).

Теперь, когда речь заходит о том, что какая-то часть вашего кода знает данные, которые были сохранены, возникает ряд дополнительных вопросов: команды, которые происходят в ProcessAllData() выше, почему они разделяют данные точно ? Могут ли разделяемые данные разделяться в памяти (в другом классе домена), добавляться в контекст и сохраняться в методе SaveChanges()? Это обеспечит вам только одно обращение к базе данных (это цель Entity Framework Unit of Work, то есть: накапливать изменения в контексте, добавлять, удалять, удалять, затем в одной операции, разговаривать с базой данных).