我正在实现一个服务层,我需要确保在一个事务中发生跨多个表的特定数量的操作。这是工作流程。
这就是它的实施方式。
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表中插入的内容在ProcessAllData调用中是不可见的,因为dbContext.SaveChanges仅在结尾处被调用。我在想,我需要以某种方式将事务范围纳入此处,但不确定如何公开应该启动事务范围的函数?
答案 0 :(得分: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();
}
答案 1 :(得分:0)
我建议重构代码,以便服务具有单一方法(在更高的抽象级别)和单一职责:处理用例。
然后,客户端类将具有
private readonly IHistoricalDataService _historicalDataService;
_historicalDataService.RearrangeSeatingArrangement(); //High level abstraction
执行上述操作的目的是确保您的服务类在单个方法中进行所有操作,如果使用原始ADO.NET,则使用事务范围包装,如果使用EF,则使用上下文对象包装。当它只能调用ONE时,不要让客户端类调用三个方法。这首先是服务类的目的:处理用例并将响应返回给客户端类(在您的情况下可能是控制器)。
现在,当确保代码的某些部分能够识别已经存在的数据时,它会带来一些额外的问题:上面的ProcessAllData()期间发生的命令,为什么它会精确地分割数据?可以将拆分的数据拆分到内存中(在另一个域类中),添加到上下文中并保存在SaveChanges()方法中吗?这将确保您只对数据库进行一次调用(这是实体框架工作单元的目的。即:在上下文中累积更改,添加,删除,udpates,然后在一个操作中,与数据库通信)。