在某些情况下,我已经在我的存储库函数中使用了事务,因为有时候我需要将数据插入到两个表中,我希望整个操作失败时都会回滚。
现在我遇到了这样的情况:我必须将多个存储库/函数的调用包装在另一个事务中,但是当其中一个函数已经在内部使用了事务时,我会收到错误信息The connection is already in a transaction and cannot participate in another transaction
。
我不想从存储库函数中删除事务,因为这意味着我必须在服务层中实现对哪些存储库函数需要事务的了解。另一方面,似乎当存储库函数已经在内部使用事务时,我不能在事务中使用它们。以下是我面临此问题的示例:
// Reverse engineered classes
public partial class TblProject
{
public TblProject()
{
TblProjectStepSequences = new HashSet<TblProjectStepSequence>();
}
public int ProjectId { get; set; }
public virtual ICollection<TblProjectStepSequence> TblProjectStepSequences { get; set; }
}
public partial class TblProjectTranslation
{
public int ProjectId { get; set; }
public string Language { get; set; }
public string ProjectName { get; set; }
public virtual TblProject Project { get; set; }
}
public partial class TblProjectStepSequence
{
public int SequenceId { get; set; }
public int ProjectId { get; set; }
public int StepId { get; set; }
public int SequencePosition { get; set; }
public virtual TblStep Step { get; set; }
public virtual TblProject Project { get; set; }
}
// Creating a project in the ProjectRepository
public async Task<int> CreateProjectAsync(TblProject project, ...)
{
using (var transaction = this.Context.Database.BeginTransaction())
{
await this.Context.TblProjects.AddAsync(project);
await this.Context.SaveChangesAsync();
// Insert translations... (project Id is required for this)
await this.Context.SaveChangesAsync();
transaction.Commit();
return entity.ProjectId;
}
}
// Creating the steps for a project in the StepRepository
public async Task<IEnumerable<int>> CreateProjectStepsAsync(int projectId, IEnumerable<TblProjectStepSequence> steps)
{
await this.Context.TblProjectStepSequences.AddRangeAsync(steps);
await this.Context.SaveChangesAsync();
return steps.Select(step =>
{
return step.SequenceId;
}
);
}
// Creating a project with its steps in the service layer
public async Task<int> CreateProjectWithStepsAsync(TblProject project, IEnumerable<TblProjectStepSequence> steps)
{
// This is basically a wrapper around Database.BeginTransaction() and IDbContextTransaction
using (Transaction transaction = await transactionService.BeginTransactionAsync())
{
int projectId = await projectRepository.CreateProjectAsync(project);
await stepRepository.CreateProjectStepsAsync(projectId, steps);
return projectId;
}
}
有没有一种方法可以在内部事务不知道可能存在外部事务的情况下将多个事务嵌套在彼此内部?
我知道从技术角度来看,可能无法真正嵌套这些事务,但我仍然需要一个解决方案,它要么使用存储库的内部事务,要么使用外部事务(如果存在),以便于在需要使用事务的存储库函数时,我不会意外地忘记使用一个事务。
SaveChanges()
之前直接添加相关实体来考虑这一点。然而,由于不同的原因,我仍然遇到“只调用一次SaveChanges()
”方法的问题。例如,我有一个实体,其中一个列的值应该设置为包含实体ID的字符串,当创建一个新实体时。由于在保存更改到数据库之前我不知道ID,所以我需要在获取ID以设置其他列的值之前调用SaveChanges()
。 - Chris