首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >事务期间的MSDTC异常: C#

事务期间的MSDTC异常: C#
EN

Stack Overflow用户
提问于 2011-06-19 10:49:50
回答 3查看 9K关注 0票数 2

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

有趣的是,使用事务的其他功能能够完成它们的事务。这使我想到了一个假设,即异常信息是一种误导性信息。

对这个问题有什么想法吗?

例外情况:“已禁用分布式事务管理器(MSDTC)的网络访问。请使用组件服务管理工具在MSDTC的安全配置中启用用于网络访问的DTC。

来源: System.Transactions

内部异常:“事务管理器禁用了对远程/网络事务的支持。(HRESULT例外:0x8004D024)“

注意:事务内部有一个for循环。会引起什么问题吗?

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

代码语言:javascript
运行
复制
    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();
    }

发展环境:视觉研究2005

框架:.Net 3.0

DB: Server 2005

当我运行查询时,选择Size,Max_Size,Data_Space_Id,File_Id,Type_Desc,Name FROM MyDB.sys.database_files,data_space_id =0--它表示( log)的大小为128。

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

谢谢

李乔

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-19 11:07:48

aspInsertUSAZipCode是否有可能与链接的服务器进行交互?如果是这样,那么它将尝试将当前本地事务提升到分布式事务(在服务器和链接服务器之间保持事务完整性)。

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

临时表的目的是在连接结束时删除该表。

票数 1
EN

Stack Overflow用户

发布于 2011-06-19 14:27:57

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

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

Services".

  • Browse

  • 通过树进入“控制面板”->管理“->”组件,直到您到达一个名为"Local“或类似于that.

  • Right-click的节点,并选择"Properties".

  • Go以”安全“,并确保允许网络访问,并允许与DTC.

  • 单击”Ok“进行入站和出站通信。

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

顺便说一句,在PerformDatabaseOperation中使用之后,记得关闭连接。将其放在using块中是一个很好的实践:

代码语言:javascript
运行
复制
using (SqlConnection mySqlConnection = new .....)
{
    // Some code here...
    mySqlConnection.Open();
    // Some more code ...
}
票数 8
EN

Stack Overflow用户

发布于 2011-06-19 11:03:33

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

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6401918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档