LINQ to SQL DataContext“分布式事务已完成”错误,但没有事务处于活动状态

时间:2012-11-14 21:08:57

标签: .net sql-server linq-to-sql

似乎错误,“分布式事务已完成。要么在NULL事务的新事务中登记此会话”,这是一个普遍存在的问题,有许多讨论和不同的原因,但在环顾四周之后,我仍然无法确定在我的情况下可能会导致它。我正在使用LINQ-to-SQL DataContext派生类来查询和更新数据库,但我们所做的大约一半的更新是在直接SQL更新和通过插入,更新和删除的部分方法中的另一个API执行的更新之间分配的。 DataContext。当我们检测到SQL和第三方更新都将发生时,我们使用“TransactionScopeOption.Required”选项创建一个新的TransactionScope对象,然后检索环境事务并在同一个分布式事务中登记第三方API。

在大多数情况下,这似乎相对可靠。但有时会发生罕见且难以重现的错误。当在SubmitChanges期间由于在DataContext上的部分方法期间验证失败而发生预期(用户)错误时,我们的代码将在不调用Complete的情况下处理TransactionScope并将错误报告给用户。如果再次尝试相同的事务,有时它会起作用,但有时我们会报告错误意外的DTC错误。

真正奇怪的是,如果我执行Debug.WriteLine来检查System.Transactions.Transaction.Current的状态,那么我就不能再重新判断错误了。如果我更改代码以将相同的信息报告给文本文件而不是调试流,我可以轻松地重现错误。这让我怀疑是否存在一些奇怪的线程同步问题。

在搜索答案时,我偶然发现了一个让我尝试使用RequiresNew而不是Required作为TransactionScopeOption的主题。但是在类似的情况下会导致不同的错误:“ExecuteReader需要一个开放且可用的连接。连接的当前状态是Open。​​”

我已经确认(通过调试输出到文件)当我在DataContext上调用Refresh时环境事务是Nothing,然后在框架的Refresh实现中的某处是两种情况下都发生错误的地方。我很难过。为什么我认为我正在尝试参与交易?

编辑:这个谜题不断变得更加混乱。我再次尝试了同样的事情(仍然使用RequiresNew)并获得了“内部.Net Framework数据提供程序错误12”。是否有关于此错误12的任何信息可能会提供有关这里的内容的线索?

1 个答案:

答案 0 :(得分:0)

Internal .Net Framework Data Provider Error 12是一个很好的线索,可以发生对非线程安全数据框架的多线程访问。事实上,我能够确认DataContext.Refresh正在一个线程上执行,同时在另一个线程上引发了System.Transactions.Transaction.TransactionCompleted事件,并且我有一个事件处理程序代码,其中包含其他成员那里的交易(第三方API)。显然,同时尝试这样做会引起一些我并不完全理解的混乱,但通过确保两个线程不能同时与连接/事务交互,可以轻松避免这种混乱。我建议使用SyncLock(VB.NET),lock(C#)或Threading.Monitor.EnterThreading.Monitor.Exit来帮助确保多个线程避免访问数据提供者同一时间。