var allTasks = arrayOfConfigLists
.Select(configList =>
Task.Run(() => SaveConfigurations(configList))
.ToArray();
Task.WaitAll(allTasks);
每次调用SaveConfigurations都会创建一个新的上下文来运行完成。
private static void SaveConfigurations(List<Configuration> configs)
{
using (var dc = new ConfigContext())
{
dc.Configuration.AutoDetectChangesEnabled = false;
dc.SaveConfigurations(configs);
}
}
目前代码运行相对高效,考虑到这可能不是最优的处理方式。但如果其中一个SaveConfigurations失败,我意识到需要回滚任何已保存到数据库中的其他配置。
经过一些研究,我将现有框架升级到4.5.1,并利用新的TransactionScopeAsyncFlowOption.Enabled选项来处理异步调用。我进行了以下更改:
using (var scope =
new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
//... allTasks code snippet from above
scope.Complete();
}
在这个阶段,我开始聚合各种有趣的错误:
该操作对于事务状态无效。
底层提供程序在打开时失败。
已禁用分布式事务管理器(MSDTC)的网络访问。
事务管理器已禁用其对远程/网络事务的支持。
我不明白的是为什么引入TransactionScope会创建这么多问题。我假设我对异步调用与EF的交互以及TransactionScope如何包装这些调用有基本的误解,但我弄不清楚。而且我真的不知道MSDTC异常涉及什么。
对于如何在对同一数据库进行异步调用时具有回滚功能,您有什么想法吗?有没有更好的处理这种情况的方法?
更新: 在查看此处的文档(链接)后,我发现Database.BeginTransaction()是首选的EF调用。然而,这假定所有更改都将在同一个上下文中发生,但实际情况并非如此。除了创建虚拟上下文并传递事务之外,我认为这不能解决我的问题。