SQLCLR存储过程中的“MS DTC已取消分布式事务”错误

时间:2016-04-01 09:16:55

标签: c# sql-server sqlclr msdtc

我需要将一些代码从旧项目移动到新项目。旧项目使用DLL与存储过程(32位版本),但我需要在64位SQL Server上使用此DLL,因此我需要重写这些过程。

我正在使用SQL Server 2008的存储过程编写dll。在Management Studio中我加载程序集,然后使用以下命令创建过程:

CREATE PROCEDURE ...
AS EXTERNAL NAME 

旧的DLL过程只是使用与远程SQL Server的新连接来在其上运行存储过程并返回结果。

因此,在我的程序中,我为远程服务器创建了一个SqlConnection并在远程服务器上运行存储过程:

using (SqlConnection connection = new SqlConnection(String.Format("User ID={0};Password={1};Persist Security Info=True;Initial Catalog={2};Data Source={3}", Login, Password, DBName, ServerName)))
{
    connection.Open();
    SqlCommand command = new SqlCommand("Exec ProcName", connection);
    SqlDataReader reader = command.ExecuteReader();
    SqlContext.Pipe.Send(reader);
}

如果我在SSMS中运行此过程,它可以正常工作。但在旧项目中,它会引发错误:

  

Microsoft分布式事务处理协调器(MS DTC)已取消分布式事务。

MSDTC服务运行,我设置了所有安全参数。如何解决?也许还有其他方法来运行远程存储过程(链接服务器),但我需要保存旧的项目功能。

1 个答案:

答案 0 :(得分:1)

有几件事情不太正确:

  1. 你为什么要重写任何东西?如果您有代码,最糟糕的情况就是重新编译新架构。

  2. 你为什么一开始做任何事情?代码应该针对“任何CPU”(在“项目属性”的“SQLCLR构建”选项卡中的“平台目标”下)编译,而不是专门针对32位或64位。如果它已经在“任何CPU”下编译,那么就无所事事了。在开始任何重新编译和/或重写之前,您是否在新系统上进行了测试?

  3. 不要使用String.Format来创建连接字符串。相反,请使用SqlConnectionStringBuilder

    SqlConnectionStringBuilder _ConnectionStringBuilder =
                                     new SqlConnectionStringBuilder();
    
    _ConnectionStringBuilder.DataSource = ServerName;
    _ConnectionStringBuilder.InitialCatalog = DBName;
    _ConnectionStringBuilder.UserID = Login;
    _ConnectionStringBuilder.Password = Password;
    
  4. 除非您绝对别无选择且必须使用此选项,否则请勿指定Persist Security Info=True;

  5. 使用:

    创建new SqlCommand(),而不是使用SqlCommand
    using(SqlCommand command = connection.CreateCommand())
    {
      command.CommandText = "Exec ProcName";
    }
    
  6. 请务必同时指定command.CommandType = CommandType.StoredProcedure;,以便它执行实际的RPC调用而不是即席查询。这将要求您从“EXEC ProcName”的当前CommandText中删除“EXEC”的文本;您只能指定[[DatabaseName.]SchemaName.]ProcName

  7. SqlDataReader是一次性对象,就像SqlConnectionSqlCommand一样,因此SqlDataReader reader = command.ExecuteReader()应该包含在using()构造中。

  8. 一旦上述项目得到纠正,您就可以通过简单地设置SqlConnectionStringBuilder的以下属性来修复错误:_ConnectionStringBuilder.Enlist = false

    有关使用SQLCLR的更多详细信息和示例,请参阅我在SQL Server Central上就此主题撰写的系列文章:Stairway to SQLCLR(阅读该网站上的内容需要免费注册)。 / p>