C# ASP.Net:长时间数据库操作期间出现异常(仅有时)

发布于 2024-11-16 05:07:47 字数 3354 浏览 2 评论 0原文

我们有一个 ASP.Net Web 应用程序,它使用 WCF 连接到其业务层。有时,当它执行巨大的操作时,我会遇到异常。有趣的是,当我第一次运行它时,它就成功了。之后它抛出异常。

异常:套接字连接被中止。

操作是将邮政编码从 csv 文件上传到数据库表中。首先,我们从 csv 文件中读取并生成一个冗长的邮政编码字符串。这将传递给存储过程并执行数据库操作。

注 1:)当我放置断点并进行测试时,很明显,字符串的创建(从 csv 获取数据并附加之后)非常快(不到一分钟)。

注 2:)我删除了事务(从 C# 代码中)并进行了测试,即使如此,异常仍然存在。

注3:)csv中有十万条记录。每行有四列(邮政编码、城市、县、州)。 csv 文件的大小为 3MB。

我对事务日志的大小有疑问。然后我使用以下命令缩小了日志文件。 DBCC SHRINKFILE('MyDB_log', 1) GO

然后我使用 SELECT [Size],Max_Size,Data_Space_Id,[File_Id],Type_Desc,[Name] FROM FRAMIS_R2075.sys.database_files 检查日志大小,其中 data_space_id = 0

大小为 128;最大尺寸为 268435456; Type_Desc = “LOG”

即使在收缩之后,异常仍然出现。

框架:.Net 3.0

DB:SQL Server 2005

嗯,业务层好像也有异常,我又等了20分钟。它说,“当读取器被调用时,尝试调用 Read 无效”。看到这一点,我删除了 DbDataReader 并使用 SqlCommand 来更新数据库表。业务层再次出现异常,大约20分钟后说“超时异常”。知道为什么会发生这种情况吗?

  private void ProcessDatabaseOperationsForZipCode(StringBuilder dataStringToProcess, int UserID)
    {
        int CountOfUnchangedZipCode = 0;
        string strRetiredZipCode = "";
        string strNewZipCode = "";
        dataStringToProcess.Remove(dataStringToProcess.Length - 1, 1);


        if (dataStringToProcess.Length > 0)
        {

            //TimeSpan.FromMinutes(0) - to make transaction scope as infinite.
            using (TransactionScope transaction = TransactionScopeFactory.GetTransactionScope(TimeSpan.FromMinutes(0)))
            {


                SqlConnection mySqlConnection = new SqlConnection("data source=myServer;initial catalog=myDB; Integrated Security=SSPI;");
                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();

         //Database db = DatabaseFactory.CreateDatabase();
                //DbCommand cmd = db.GetStoredProcCommand("aspInsertUSAZipCode");
                //cmd.CommandTimeout = 0;
                //db.AddInParameter(cmd, "@DataRows", DbType.String, dataStringToProcess.ToString());
                //db.AddInParameter(cmd, "currDate", DbType.DateTime, DateTime.Now);
                //db.AddInParameter(cmd, "userID", DbType.Int32, UserID);
                //db.AddOutParameter(cmd, "CountOfUnchangedZipCode", DbType.String, 1000);


                //using (DbDataReader rdrUpgradeTypes = (DbDataReader)db.ExecuteReader(cmd))
                //{
                //    //while (rdrUpgradeTypes.Read())
                //    //{
                //    //    if (!String.IsNullOrEmpty(Utility.GetString(rdrUpgradeTypes, "NewZipCode")))
                //    //    {
                //    //        strNewZipCode = strNewZipCode + "," + Utility.GetString(rdrUpgradeTypes, "NewZipCode");
                //    //    }
                //    //}
                //}


                transaction.Complete();

            }
        }


    }

We have a ASP.Net web application that connects to its business layer using WCF. Sometimes, I am getting exception when it is performing a huge operation. The interesting part is when I ran it for the first time it was successful. Afterwards it is throwing exception.

Exception: The socket connection was aborted.

The operation is that it uploads zipcodes into database tables from a csv file. First we read from csv file and make a single lengthy string of zipcodes. This is passed to the stored procedure and the database operations are performed.

Note 1:) When I placed breakpoint and tested, it is clear that the creation of the string (after taking data from csv and appending) is pretty fast (less than one minute).

Note 2:) I removed the transaction (from C# code) and tested, even then the exception is there.

Note 3:) There are one lakh (one hundred thousand) records in csv. Each row has four columns (ZipCode, City, County, State). Size of the csv file is 3MB.

I had a doubt about the transaction log size. Then I shrinked the log file using the following command.
DBCC SHRINKFILE('MyDB_log', 1) GO

Then I checked the log size using SELECT [Size],Max_Size,Data_Space_Id,[File_Id],Type_Desc,[Name] FROM FRAMIS_R2075.sys.database_files WHERE data_space_id = 0

The Size is 128; Max Size is 268435456; Type_Desc = “LOG”

Even after shrinking the exception is still coming.

Framework: .Net 3.0

DB: SQL Server 2005

Well, it seems like there is an excpetion in the business layer too, when I waited for 20 more minutes. It said, “Invalid Attempt to call Read when the reader is called”. By seeing this, I removed the DbDataReader and used SqlCommand to update the database tables. Again, there came an exception in business layer, after some 20 minutes saying “Timeout exception”. Any idea why this is happening?

  private void ProcessDatabaseOperationsForZipCode(StringBuilder dataStringToProcess, int UserID)
    {
        int CountOfUnchangedZipCode = 0;
        string strRetiredZipCode = "";
        string strNewZipCode = "";
        dataStringToProcess.Remove(dataStringToProcess.Length - 1, 1);


        if (dataStringToProcess.Length > 0)
        {

            //TimeSpan.FromMinutes(0) - to make transaction scope as infinite.
            using (TransactionScope transaction = TransactionScopeFactory.GetTransactionScope(TimeSpan.FromMinutes(0)))
            {


                SqlConnection mySqlConnection = new SqlConnection("data source=myServer;initial catalog=myDB; Integrated Security=SSPI;");
                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();

         //Database db = DatabaseFactory.CreateDatabase();
                //DbCommand cmd = db.GetStoredProcCommand("aspInsertUSAZipCode");
                //cmd.CommandTimeout = 0;
                //db.AddInParameter(cmd, "@DataRows", DbType.String, dataStringToProcess.ToString());
                //db.AddInParameter(cmd, "currDate", DbType.DateTime, DateTime.Now);
                //db.AddInParameter(cmd, "userID", DbType.Int32, UserID);
                //db.AddOutParameter(cmd, "CountOfUnchangedZipCode", DbType.String, 1000);


                //using (DbDataReader rdrUpgradeTypes = (DbDataReader)db.ExecuteReader(cmd))
                //{
                //    //while (rdrUpgradeTypes.Read())
                //    //{
                //    //    if (!String.IsNullOrEmpty(Utility.GetString(rdrUpgradeTypes, "NewZipCode")))
                //    //    {
                //    //        strNewZipCode = strNewZipCode + "," + Utility.GetString(rdrUpgradeTypes, "NewZipCode");
                //    //    }
                //    //}
                //}


                transaction.Complete();

            }
        }


    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三生殊途 2024-11-23 05:07:47

问题很可能是与 SQL Server 的连接超时 - 连接和命令的默认超时均为 30 秒。

您可以延长超时(在连接字符串和代码中)或将更新分解为块。

The problem is likely that the connection to the SQL Server times out - the default timeout for both connections and commands is 30 seconds.

You can either up the timeout (on the connection string and in code) or break up the updates into chunks.

渡你暖光 2024-11-23 05:07:47

感谢奥德耐心解答我的问题。当我将巨大的数据库操作分成小批量时(配置 MSDTC 后),我的问题得到了解决。

在大型数据库操作过程中,可能会出现内存不足的错误。但如果该错误位于事务内部,则可能不可见。

1)删除事务,查看是否有“内存不足”异常。

2) 将大型数据库操作分解为小批量,以消除“内存不足”异常

3) 在应用层和数据库中配置 MSDTC

4) 确保 WCF 不会突然超时。根据数据库操作应该有足够的时间。

5) 观察数据库服务器重新启动时的行为(这是最后一个选项)

中提供了一些有用的信息

资源池“default”中没有足够的系统内存来运行此查询

事务期间出现 MSDTC 异常:C#

C# ASP.Net:长数据库期间出现异常(仅有时)操作

SQL Server 2005 错误 701 - 内存不足

其他一些检查:

1) 运行数据库引擎的windows帐户是否具有“锁定内存页权限”?

2) 检查SQL Sever 服务包版本。

3) 检查虚拟内存分页文件的大小

4) 检查最大服务器内存

5) 确定 MemToLeave 设置

6) “SQL Server 内存配置和 MemToLeave”

Thanks Oded for patiently answering my questions. My problem got resolved when I splitted the huge database operations into small batches (after configuring MSDTC).

During Large Database operations, insufficient memory error may come. But this error may not be visible if it is inside a Transaction.

1) Remove transaction and see if “Insufficient Memory” exception is available.

2) Breakdown large database operations into small batches to remove the “Insufficient Memory” exception

3) Configure MSDTC in app tier and database

4) Ensure that WCF does not time out abruptly. It should have enough time based on database operations.

5) Observe the behavior when the database server is restarted (This is last option)

Some useful information available in

There is insufficient system memory in resource pool 'default' to run this query

MSDTC Exception during Transaction: C#

C# ASP.Net: Exception (some times only) during long database operation

SQL Server 2005 Error 701 - out of memory

Some other checks:

1) Whether the windows account under which the database engine is running have "Lock pages in memory permission"?

2) Chek SQL Sever service pack version.

3) Check size of virtual memory paging file

4) Check max server memory

5) Determining MemToLeave Settings

6) "SQL Server Memory Configuration and MemToLeave"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文