I am implementing a service layer where I need to make sure that certain number of operations across multiple tables happen in a transaction. Here is the work flow.
This is how its implemented.
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();
}
}
Here is how this class methods are been called.
HistoricalDataService service = new HistoricalDataService (dbcontext);
service.AddHistoricalData(HistoricalData instance);
service.ProcessAllData();
service.SaveData();
Problem with this approach is that whatever is inserted in HistoricalData table during call to AddHistoricalData method is not visible in the ProcessAllData call, because dbContext.SaveChanges is called only at the end. I am thinking that I need to somehow bring transaction scope in here but not sure how to expose a function where that transaction scope should be started?
There are different ways you can do this. Try this (untested, but 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();
}
}
Use as such:
HistoricalDataService service = new HistoricalDataService (dbcontext);
try
{
service.AddHistoricalData(HistoricalData instance);
service.ProcessAllData();
service.SaveData();
}
catch (Exception ex)
{
service.Rollback();
}