对 Sql Server 2000 的 TransactionScope 错误 - 合作事务管理器已禁用其对远程/网络事务的支持

5

我正在尝试为我的Linq-to-Sql操作建立一个简单的事务,针对我的Sql 2000数据库。使用TransactionScope,代码如下:

using (TransactionScope transaction = new TransactionScope())
{
    try
        {
        Store.DBDataContext dc = new Store.DBDataContext();
        Store.Product product = GetProduct("foo");
        dc.InsertOnSubmit(product);
        dc.SubmitChanges();
        transaction.Complete();
    }
    catch (Exception ex)
    {                
        throw ex;
    }
}

然而,我不断遇到以下错误:
合作伙伴事务管理器已禁用其对远程/网络事务的支持。 (HRESULT 异常: 0x8004D025)
但是,如果我使用传统事务设置事务,则可以正常工作。 因此,以下内容有效:
Store.DBDataContext dc = new Store.DBDataContext();
try
{
    dc.Connection.Open();
    dc.Transaction = dc.Connection.BeginTransaction();
    Store.Product product = GetProduct("foo");
    dc.InsertOnSubmit(product);
    dc.SubmitChanges(); 
    dc.Transaction.Commit();
}
catch (Exception ex)
{
    dc.Transaction.Rollback();
    throw ex;
}
finally
{
    dc.Connection.Close();      
    dc.Transaction = null;
}

我想知道TransactionScope在底层是否与我的第二个实现有所不同。如果没有,那么不使用TransactionScope会失去什么?此外,对导致错误的原因有任何指导也很好。我已确认MSDTC在SQL Server和客户端机器上都在运行。

5个回答

6

看这里:

使用System.Transactions和Microsoft SQL Server 2000进行快速事务处理 http://blogs.msdn.com/florinlazar/archive/2005/09/29/475546.aspx

还有这里:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=230390&SiteID=1

首先,请验证数据库服务器计算机和客户端计算机上是否运行“分布式事务协调器”服务
1. 转到“管理工具>服务”
2. 如果未运行,请开启“分布式事务协调器”服务

如果它正在运行,而且客户端应用程序不在与数据库服务器相同的计算机上,请在运行数据库服务器的计算机上执行以下操作
1. 转到“管理工具>组件服务”
2. 在左侧导航树中,转到“组件服务>计算机>我的计算机”(您可能需要双击并等待,因为某些节点需要时间扩展)
3. 右键单击“My Computer”,选择“属性”
4. 选择“MSDTC”选项卡
5. 点击“安全配置”
6. 确保您勾选“Network DTC Access”、“Allow Remote Client”、“Allow Inbound/Outbound”、“Enable TIP”(某些选项可能不必要,可以尝试获取您的配置)
7. 服务将重新启动
8. 如果仍然无法工作,请重新启动服务器 (这是以前使我发疯的事情)

在客户端计算机上,使用与上述相同的过程打开“安全配置”设置,确保您检查了“Network DTC Access”、“Allow Inbound/Outbound”选项,必要时重启服务和计算机。

在SQL服务器服务管理器中,单击“Service”下拉列表,选择“分布式事务协调器”,它也应在您的服务器计算机上运行。


在Florin Lazar的帖子中提到的DatabaseTransactionAdapter解决了问题。我会在回复中发布我的实现代码。 - Bramha Ghosh
配置MSDTC的说明似乎不适用于Windows 7。在MSDTC选项卡下,我只有一个选项,它说:使用本地协调程序或指定远程主机使用。 - Myster
1
我找到了在Windows 7和2008上查找这些设置的指南!请看这里:http://msdn.microsoft.com/zh-cn/library/aa561924(BTS.20).aspx - skb

3

Keith Sirmons指向的Florin Lazar帖子中的DatabaseTransactionAdapter实现似乎很管用。以下是我的调用代码:

Store.DBDataContext dc = new Store.DBDataContext();
using (TransactionScope transaction = new TransactionScope())
{
    try
    {
        var dbAdapter = new DatabaseTransactionAdapter(dc.Connection);
        dc.Connection.Open();
        dbAdapter.Begin();
        dc.Transaction = (SqlTransaction)dbAdapter.Transaction;
        Store.Product product = GetProduct("foo");
        dc.InsertOnSubmit(product);
        dc.SubmitChanges();
        transaction.Complete();
    }
    catch (Exception ex)
    {                
        throw ex;
    }
}

唯一让我感到不安的是,尽管它没有在“using”语句中声明,但我没有明确关闭连接。

但根据Florin Lazar的说法,这是有意为之。

而且,您也不必关闭连接,因为连接应该保持打开状态,直到事务完成,这发生在“using”语句结束之后。适配器将拥有连接的生命周期,并在完成后关闭它。


1
我在这里发布下面的解决方案,因为经过一些搜索,这是我最终找到的地方,所以其他人也可能会来这里。 我试图使用EF 6调用存储过程,但由于存储过程使用了链接服务器,所以出现了类似的错误。

无法执行操作,因为OLE DB提供程序 _ for linked server _ 无法开始分布式事务

合作交易管理器已禁用其对远程/网络事务的支持

转向SQL客户端确实解决了我的问题,这也为我确认了这是一个EF的问题。

基于EF模型生成的方法尝试:

db.SomeStoredProcedure();

基于 ExecuteSqlCommand 的尝试:

db.Database.ExecuteSqlCommand("exec [SomeDB].[dbo].[SomeStoredProcedure]");

With:

var connectionString = db.Database.Connection.ConnectionString;
var connection = new System.Data.SqlClient.SqlConnection(connectionString);    
var cmd = connection.CreateCommand();
cmd.CommandText = "exec [SomeDB].[dbo].[SomeStoredProcedure]";

connection.Open();
var result = cmd.ExecuteNonQuery();

那段代码可以缩短,但我认为这个版本更方便调试和逐步执行。

我不认为Sql Client一定是首选,但如果有其他人遇到类似问题并通过谷歌搜索到这里,我觉得这个值得分享。


1
在Windows 2008或更高版本上启用此功能的步骤如下:
首先,确认“分布式事务协调器”服务在数据库服务器计算机和客户端计算机上都正在运行。 1. 进入“管理工具>服务”。 2. 如果“分布式事务协调器”服务未运行,请启动它。 如果该服务正在运行且客户端应用程序不在与数据库服务器相同的计算机上,请执行以下操作: 1. 进入“管理工具>组件服务”。 2. 在左侧导航树中,转到“组件服务>计算机>我的计算机>分布式事务协调器”(您可能需要双击并等待一些节点扩展)。 3. 右键单击“本地DTC”,选择“属性”。 4. 选择“安全”选项卡。 5. 确保您勾选了“网络DTC访问”、“允许远程客户端”、“允许入站/出站”。 6. 服务将重新启动。 7. 但是,如果仍然无法正常工作,则可能需要重新启动服务器(这是我以前遇到的问题)。 在客户端计算机上,使用同样的方法打开“安全配置”设置,确保您勾选了“网络DTC访问”、“允许入站/出站”选项,必要时重启服务和计算机。 在SQL服务器服务管理器中,单击“服务”下拉菜单,选择“分布式事务协调器”,它也应该在您的服务器计算机上运行。

0
更多注意事项: - 服务器配置指南 启用网络COM+访问(Windows Server 2003) 开始 ==> 控制面板 ==> 添加或删除程序 ==> 添加/删除Windows组件,选择应用程序服务器,然后单击详细信息。 单击启用网络COM+访问,然后单击确定。 单击下一步,然后单击完成。
- 如果两个服务器之间有防火墙,请在此范围端口上打开防火墙的出入口: 单击开始 ==> 控制面板 ==> 管理工具 ==> 组件服务。 展开组件服务,展开计算机,在我的计算机上单击右键,然后选择属性。 在“我的计算机属性”窗口中,单击默认协议选项卡,单击面向连接的TCP/IP并选择属性。 在新窗口中,单击添加并输入新的DTC端口范围。 单击确定以应用这些更改。 必须重新启动服务器才能使新更改生效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接