C# 从.NET应用程序中,内部带有链接服务器选择查询的简单存储过程只工作一次

C# 从.NET应用程序中,内部带有链接服务器选择查询的简单存储过程只工作一次,c#,.net,linked-server,sql-server-2008-express,C#,.net,Linked Server,Sql Server 2008 Express,我玩了几天与链接服务器使用的存储过程恼人的问题。在服务器上,我共享了数据库。服务器正在运行MS SQL server 2008 EE sp3。作为新用户,我无法放置图像,因此我将尝试不放置图像 假设我有一个存储过程 CREATE PROCEDURE [dbo].[spSynchronizeArticles] -- Add the parameters for the stored procedure here ( @pDebug bit, @siteId bigint

我玩了几天与链接服务器使用的存储过程恼人的问题。在服务器上,我共享了数据库。服务器正在运行MS SQL server 2008 EE sp3。作为新用户,我无法放置图像,因此我将尝试不放置图像

假设我有一个存储过程

CREATE PROCEDURE [dbo].[spSynchronizeArticles] 
    -- Add the parameters for the stored procedure here
(
    @pDebug bit,
    @siteId bigint
)
AS
BEGIN

  SELECT *
  FROM [LinkedServer].[MyDatabase].dbo.Storages 
  WHERE Storage.siteId = @siteId

  RETURN 0

END
配置链接服务器的位置

编辑:

当我从MS SQL Management studio运行查询时,它总是成功运行。当我从c应用程序代码运行查询时

StringBuilder sb;
    public bool ActualizeArticlesFromServer(Int64 siteId, out string messages)
    {
      SqlCommand sqlCmd = new SqlCommand("spSynchronizeArticles");
      try
      {
        sb = new StringBuilder();
        sqlCmd.CommandType = CommandType.StoredProcedure;
        sqlCmd.Parameters.AddWithValue("@pDebug", "false");
        sqlCmd.Parameters.AddWithValue("@siteId", siteId);

        // Return value as parameter
        SqlParameter returnValue = new SqlParameter("returnVal", SqlDbType.Int);
        returnValue.Direction = ParameterDirection.ReturnValue;
        sqlCmd.Parameters.Add(returnValue);

        using (SqlConnection conn = new SqlConnection(Context.LocalData.ConnectionString))
        {
          try
          {
            try
            {
              conn.Open();
              sqlCmd.Connection = conn;
              //TODO: find out how to print from stored procedure
              //((SqlConnection)Context.LocalData.Connection).InfoMessage += new SqlInfoMessageEventHandler(Connection_InfoMessage);
               sqlCmd.ExecuteScalar();
            }
            catch (Exception ex)
            {
              Log.LogMethodException(ex);
              return false;
            }
          }
          finally
          {
            try
            {
              conn.Close();
            }
            catch (Exception ex) 
            {
              Log.LogMethodException(ex);
            }
          }
        }

        return Convert.ToInt64(returnValue.Value) == 0;
      }
      finally
      {
        messages = sb.ToString();
      }
    }
我在应用程序中有用户列表,但它是内部解决的。没有windows用户

当我为实际用户运行此代码时,一切正常,我可以运行查询更多时间。然后我更改了用户,并尝试从上面的代码执行过程,我得到了异常

System.Data.SqlClient.SqlException (0x80131904): The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "someServer" was unable to begin a distributed transaction.
当我重新启动整个应用程序时,查询再次正常工作。我不知道它是否与连接池或什么有关

我认为分布式事务以某种方式挂起,但在SQL中没有使用任何事务

在DTC统计信息中,我可以看到激活的事务,即使触发了异常

我已经在客户机和服务器上设置了DTC组件,但我希望它足够清晰

Network DTC Access checked
Allow inbound true
Allow outbound true
No authentication Required
SQL server服务器安装在带有Microsoft Windows server 2008的虚拟计算机上。在Windows server和虚拟Windows server上设置DTC时。防火墙是为了在服务器和虚拟机上进行测试而推出的

编辑2:

嗯。所以我做了一些研究,看起来@JanVanHerck是对的。这对我来说仍然很困惑,但我会尝试写下我所做的

我关闭MS DTC 第一次运行我的应用程序代码来执行存储过程并运行良好时 然后我注销了,我的注销方法做了一些事情,我解释如下。 我用相同的用户名登录并不重要,我运行我的应用程序代码来执行存储过程,但计算机上没有运行MS DTC的情况除外。 注意:存储过程中没有事务,也没有分布式事务

所以我检查了注销方法,发现我正在更新事务中的一个本地表——我用代码注释了事务,一切都正常

我会尝试把它放在生产系统中,并会看到,但我们在这里有一些改进。谢谢@JanVanHerck。实际上,我以前并没有检查我的代码,因为我不知道它会对执行过程产生影响


但有趣的是,即使仅在本地数据库中使用事务后,MS DTC也会出现

在我看来,不应该在您提供的代码中寻找错误,而应该在用户切换方法中寻找错误,留下一些混乱。@JanVanHerck:我会检查一下,但是应用程序已经运行了几年,所有SQL操作都没有问题,除了这个。我正在调用更多的存储过程,这些存储过程只能从代码中使用本地数据库。在这种情况下,我一直使用SQLConnection作为新对象,但我认为有一些.NET正在管理的池,我不知道会有什么问题以及如何找到它。
Network DTC Access checked
Allow inbound true
Allow outbound true
No authentication Required