我目前正在使用TransactionScope来管理我的数据层中的事务,但我一直遇到嵌套事务和异步的问题,在嵌套事务期间连接似乎关闭或者事务被提升为MSDTC.我没有找到确切的问题,但在阅读之后看起来这个场景并没有得到特别好的支持,我应该使用Database.BeginTransaction()代替.
我的问题是我无法找到有关Database.BeginTransaction()如何与嵌套事务一起工作的信息,特别是在我想要使用环境事务而不是创建新事务的场景中.我怀疑它并不打算以这种方式工作,如果我想管理嵌套事务,我应该抽象出事务管理来给我更多控制权.
我不想添加不必要的抽象层,我想知道是否有人有这方面的经验,并且可以在嵌套在另一个事务中时确认Database.BeginTransaction()的行为?
有关我的DAL的其他信息:基于CQS模式,我倾向于在命令或查询处理程序中封装Db相关代码,因此这种嵌套如何发生的简化/设计示例将是:
public class AddBlogPostHandler
{
private readonly MyDbContext _myDbContext;
public AddBlogPostHandler(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public async Task ExecuteAsync(AddBlogPostCommand command)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
// .. code to create and add a draft blog post to the context
await _myDbContext.SaveChangesAsync();
var publishBlogPostCommand = new PublishBlogPostCommand();
// ..set some variables on the PublishBlogPostCommand
await PublishBlogPostAsync(command);
scope.Complete();
}
}
}
public class PublishBlogPostHandler
{
private readonly MyDbContext _myDbContext;
public PublishBlogPostHandler(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public async Task ExecuteAsync(PublishBlogPostCommand command)
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
// .. some code to do one set of update
await _myDbContext.SaveChangesAsync();
// .. some other db updates that need to be run separately
await _myDbContext.SaveChangesAsync();
scope.Complete();
}
}
}
usr.. 7
在内部事务可以独立提交或回滚的意义上,没有嵌套事务这样的事情.嵌套事务实际上只保留引用计数.在最后一次提交时,我们得到一个物理提交.在第一次回滚时,我们获得了物理回滚.只是确保你知道这一点.
避免使用MSDTC非常重要.无论是with TransactionScope
还是with都可以BeginTransaction
.使用前者,您需要Open
在范围内显式连接,以便EF不会一直打开新连接.
正如你在这个问题中所读到的,这是EF中的一个缺陷(L2S没有).请花点时间对问题发表评论,以确保团队了解客户遇到此问题.
特别是在我想要使用环境事务而不是创建新事务的场景中.
这非常适合TransactionScope
.我认为你的转变BeginTransaction
是基于一种误解.也许你可以在评论中澄清一下.
嵌套在另一个事务中时确认Database.BeginTransaction()的行为
在第一段中解释.
有关我的DAL的其他信息:基于CQS模式,我倾向于在命令或查询处理程序中封装Db相关代码,因此这种嵌套如何发生的简化/设计示例将是:
除了丢失的db.Connection.Open()
调用之外,代码看起来很好(如上所述).
此模式将支持在同一事务中执行多个查询和命令.只需在其周围包裹另一个范围.确保不要打开两次连接,例如conn.State
在采取措施前进行检查.
在内部事务可以独立提交或回滚的意义上,没有嵌套事务这样的事情.嵌套事务实际上只保留引用计数.在最后一次提交时,我们得到一个物理提交.在第一次回滚时,我们获得了物理回滚.只是确保你知道这一点.
避免使用MSDTC非常重要.无论是with TransactionScope
还是with都可以BeginTransaction
.使用前者,您需要Open
在范围内显式连接,以便EF不会一直打开新连接.
正如你在这个问题中所读到的,这是EF中的一个缺陷(L2S没有).请花点时间对问题发表评论,以确保团队了解客户遇到此问题.
特别是在我想要使用环境事务而不是创建新事务的场景中.
这非常适合TransactionScope
.我认为你的转变BeginTransaction
是基于一种误解.也许你可以在评论中澄清一下.
嵌套在另一个事务中时确认Database.BeginTransaction()的行为
在第一段中解释.
有关我的DAL的其他信息:基于CQS模式,我倾向于在命令或查询处理程序中封装Db相关代码,因此这种嵌套如何发生的简化/设计示例将是:
除了丢失的db.Connection.Open()
调用之外,代码看起来很好(如上所述).
此模式将支持在同一事务中执行多个查询和命令.只需在其周围包裹另一个范围.确保不要打开两次连接,例如conn.State
在采取措施前进行检查.