SQL Server 2005 - 事务期间的 MSDTC 异常: C#

本文关键字:MSDTC 异常 Server 2005 事务 SQL | 更新日期: 2023-09-27 17:59:26

我在 C# 应用程序中的事务中收到 MSDTC 异常。该功能是在从csv文件读取后将十万(十万(邮政编码记录上传到数据库表中。此操作在大约 20 个批处理数据库操作(每个批处理包含 5000 条记录(中完成。如果我不使用事务,该功能工作正常。

有趣的是,使用事务的其他功能能够完成其事务。这使我假设异常消息具有误导性。

关于可能是什么问题的任何想法?

异常:"分布式事务管理器 (MSDTC( 的网络访问已被禁用。请使用组件服务管理工具在 MSDTC 的安全配置中启用 DTC 以进行网络访问。

来源:系统交易

内部异常:"事务管理器已禁用其对远程/网络事务的支持。(HRESULT的例外情况:0x8004D024(">

注意:事务中有一个 for 循环。它会导致任何问题吗?

实际要求是:邮政编码表中有一些现有的邮政编码。每个月,管理员都会上传新的邮政编码 csv 文件。将插入来自 csv 的新项目。在csv中不可用(但存在于数据库中(的邮政编码被视为已停用并被删除。已停用的邮政编码列表将返回到用户界面。新添加的邮政编码也需要返回。

    private void ProcessZipCodes(StringBuilder dataStringToProcess, int UserID)
    {
        int CountOfUnchangedZipCode = 0;
        string strRetiredZipCode = "";
        string strNewZipCode = "";
        dataStringToProcess.Remove(dataStringToProcess.Length - 1, 1);
        if (dataStringToProcess.Length > 0)
        {
            List<string> batchDataStringList = GetDataStringInBatches(dataStringToProcess);
           //TimeSpan.FromMinutes(0) - to make transaction scope as infinite.
            using (TransactionScope transaction = TransactionScopeFactory.GetTransactionScope(TimeSpan.FromMinutes(0)))
            {
                foreach (string dataString in batchDataStringList)
                {
                    PerformDatabaseOperation(dataString, UserID);
                }
                transaction.Complete();
            }
        }

    }
    private List<string> GetDataStringInBatches(StringBuilder dataStringToProcess)
    {
        List<string> batchDataStringList = new List<string>();
        int loopCounter = 0;
        string currentBatchString = string.Empty;
        int numberOfRecordsinBacth = 5000;
        int sizeOfTheBatch = 0;
        List<string> individualEntriesList = new List<string>();
        string dataString = string.Empty;
        if (dataStringToProcess != null)
        {
            dataString = dataStringToProcess.ToString();
        }
        individualEntriesList.AddRange(dataString.Split(new char[] { '|' }));

        for (loopCounter = 0; loopCounter < individualEntriesList.Count; loopCounter++)
        {
            if (String.IsNullOrEmpty(currentBatchString))
            {
                currentBatchString = System.Convert.ToString(individualEntriesList[loopCounter]);
            }
            else
            {
                currentBatchString = currentBatchString+"|"+System.Convert.ToString(individualEntriesList[loopCounter]);
            }
            sizeOfTheBatch = sizeOfTheBatch + 1;
            if (sizeOfTheBatch == numberOfRecordsinBacth)
            {
                batchDataStringList.Add(currentBatchString);
                sizeOfTheBatch = 0;
                currentBatchString = String.Empty;
            }

        }
        return batchDataStringList;

    }
    private void PerformDatabaseOperation(string dataStringToProcess, int UserID)
    {
        SqlConnection mySqlConnection = new SqlConnection("data source=myServer;initial catalog=myDB; Integrated Security=SSPI; Connection Timeout=0");
        SqlCommand mySqlCommand = new SqlCommand("aspInsertUSAZipCode", mySqlConnection);
        mySqlCommand.CommandType = CommandType.StoredProcedure;
        mySqlCommand.Parameters.Add("@DataRows", dataStringToProcess.ToString());
        mySqlCommand.Parameters.Add("@currDate", DateTime.Now);
        mySqlCommand.Parameters.Add("@userID", UserID);
        mySqlCommand.Parameters.Add("@CountOfUnchangedZipCode", 1000);
        mySqlCommand.CommandTimeout = 0;
        mySqlConnection.Open();
        int numberOfRows = mySqlCommand.ExecuteNonQuery();
    }

Dev Env: Visual Studion 2005

框架:.Net 3.0

DB: SQL Server 2005

当我运行查询时,从MyDB.sys.database_files中选择[大小],Max_Size,Data_Space_Id,[File_Id],Type_Desc,[名称] 其中data_space_id = 0 --它说(日志(的大小是128

更新我们的应用程序中使用了三个不同的数据库。一个用于数据,一个用于历史记录,一个用于日志记录。当我在上面的连接字符串中输入 enlist = false 时,它暂时可以正常工作。但它在我的开发环境中。我对它是否也适用于生产持怀疑态度。对潜在风险有什么想法吗?

谢谢

利乔

SQL Server 2005 - 事务期间的 MSDTC 异常: C#

当您在TransactionScope内打开多个连接时,正在运行的事务将自动升级到分布式事务。 若要使分布式事务正常工作,必须将 SQL Server 和运行应用程序的计算机上的 MSDTC 配置为允许网络访问。 SQL Server 和本地 DTC 在运行分布式事务时进行通信。

您的问题很可能是运行应用程序的计算机上的 MSDTC 不允许网络访问,因为这是工作站的默认设置。 要解决此问题,请执行以下操作:

  1. 转到"控制面板"->"采矿"->"组件服务"。
  2. 浏览树,直到到达名为"本地DTC"或类似内容的节点。
  3. 右键单击并选择"属性"。
  4. 转到"安全性",并确保允许网络访问,并允许与DTC进行入站和出站通信。
  5. 点击"确定"。

系统可能会提示您重新启动 DTC。 UI 中似乎存在一个错误,因为即使您接受重新启动 DTC,它也不会重新启动。 相反,您必须在服务管理器中手动重新启动 DTC 服务。

顺便说一句,请记住在PerformDatabaseOperation中使用后关闭连接. 最好将其放在using块中:

using (SqlConnection mySqlConnection = new .....)
{
    // Some code here...
    mySqlConnection.Open();
    // Some more code ...
}
aspInsertUSAZipCode 是否可以

与链接服务器交互?如果是这样,那么它将尝试将当前的本地事务提升为分布式事务(在服务器和链接服务器之间保留事务完整性(。

如果无法为分布式事务配置远程服务器上的 MSDTC,则可能需要在事务外部执行此操作。我认为最好的方法是创建一个临时表,然后将您的记录SqlBulkCopy其中,然后使用服务器上的临时表执行aspInsertUSAZipCode。您可能需要使用游标。

临时表的目的是在出现问题时,在连接终止时删除该表。

您可能在事务限制中达到了某个最大数据量。

检查事件日志中是否有任何 msdtc 错误 http://technet.microsoft.com/en-us/library/cc774415(WS.10(.aspx

在单个事务中有 100,000 行会给您带来问题。

我不认为在这种情况下单个事务会起作用,您需要查看为什么在此处使用事务,并找到不同的方法来完成它。