";事务已中止”;创建新TransactionScope()时发生异常
本文关键字:TransactionScope 异常 创建 事务 quot | 更新日期: 2023-09-27 18:19:25
这是我的第一个客户端和服务器端WCF。SQL server 2008。
我被迫在windows窗体应用程序中使用TransactionScope事务,该应用程序作为WCF服务的客户端运行。我以前没有使用过这种类型的事务,通常使用connection.BeginTransaction(),我喜欢它,因为它更容易跟踪正在发生的事情。
我调用了一个函数(我希望是嵌套事务),但其中一个创建新TransactionScope实例的调用出现了"事务已中止"异常。内部异常为null。我假设事务在此之前已经回滚,但我不知道如何跟踪是否有环境事务正在进行,以及该事务的状态。
示例客户端(不是真正的代码。我已经检查了所有函数都使用scope.Commit())关于如何找到这个问题,有什么帮助吗?
(我经常收到关于必须启动MSDTC服务的错误消息,我确实这样做了,但我不明白为什么在只有一个数据库/wcf服务的情况下使用分布式)
void Function1(AMessageObj m)
{
using (var client = GetOpenWebClient())
WriteMessage(m, client);
}
void WriteMessage(AMessage m, OpenWebClient client)
{
using (var scope = new TransactionScope())
{
var audit = GetSomeAuditInfo(AMessage.UserId, client);
WriteTheMessage(AMessage, client);
WriteAudit(audit, client);
client.SetTime(DateTime.Now);
scope.Commit();
}
}
AuditRecord GetSomeAuditInfo(Int userId, OpenWebClient client)
{
var result = client.ReadAuditRecord(userId);
return AuditRecord.FromWeb(result);
}
void WriteTheMessage(AMessage msg, OpenWebClient client)
{
using (var scope = new TransactionScope())
{
client.WriteTheMessage(msg.ToWeb());
scope.Commit();
}
}
void WriteAudit(AuditRecord audit, OpenWebClient client)
{
using (var scope = new TransactionScope())
{
client.WriteAudit(audit.ToWeb());
scope.Commit();
}
}
示例服务WCF
[ServiceContract]
interface IService
{
[OperationContract]
void WriteTheMessage(WebRecord message);
[OperationContract]
WebRecord ReadAuditRecord(int userId);
[OperationContract]
void WriteAudit(WebRecord audit);
}
class MyWebService : IService
{
[OperationBehavior(TransactionScopeRequired = true)]
void IService.WriteTheMessage(WebRecord record)
{
using (var connection = GetOpenConnection())
{
dowritethings;
}
}
[OperationBehavior(TransactionScopeRequired = false)]
WebRecord IService.ReadAuditRecord(WebRecord record)
{
using (var connection = GetOpenConnection())
{
return readthings;
}
}
[OperationBehavior(TransactionScopeRequired = true)]
void IService.WriteAudit(WebRecord record)
{
using (var connection = GetOpenConnection())
{
dowritethings;
}
}
}
我在网上搜索了如何查看环境事务状态,并找到了transaction.Current属性,我将其放入了监视窗口。这显示在一个我完全错过的外部函数调用后中止。踏入那一步,我发现我呼唤回归;从创建事务和提交事务之间的函数,因此中止。
感谢您的帮助
您在服务器上打开的每个连接都是一个分布式实体。在测试过程中,您经常会从连接池中获得相同的物理连接。这是一种非常恶劣的行为,因为它会导致您在测试过程中找不到问题。此设置对数据库的行为具有不确定性。
在任何情况下,您都应该在这里拥有分布式事务,因为WCF和SQL Server是不同的资源。这应该果断地升级为使用MSDTC。
我假设交易在之前已经回滚
很有可能。对于WCF事务,您的代码总是设置了环境事务。也许,在某个地方有一些你没有注意到的例外。将调试器设置为中断所有异常。使用Fiddler观察通过导线发送的响应。也许它们包含某种错误。WCF跟踪是另一种选择。
如果这不会导致任何结果,请尝试创建一个可靠的repo。在这个过程中,你经常自己发现错误。