SQL Server和.NET内存的限制,分配和垃圾收集分配、内存、垃圾、SQL

2023-09-06 17:39:25 作者:wuli小仙女

我运行的.NET 3.5(C#)和SQL Server 2005(为客户)。我们运行code做一些回归的数学,是一个有点复杂。我收到以下错误,当我运行在我们网站的多个页面:

I am running .NET 3.5 (C#) and SQL Server 2005 (for our clients). The code that we run does some regression math and is a little complicated. I get the following error when I run multiple pages on our site:

.NET Framework execution was aborted by escalation policy because of out of memory. 
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.InvalidOperationException: 

我试图弄清楚什么是这一现象的根本原因:这是一个数据库问题,或者我的C ## code?或者是它运行查询时并发性的锁?还是别的什么东西?

I'm trying to figure out what is the root cause of this: is it a database issue or my C## code? or is it concurrency with locks when running queries? or somethin else?

在code为示数的位置:

The code is erroring here:

erver.ScriptTimeout = 300;
        string returnCode = string.Empty;
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MainDll"].ToString())) {
            connection.Open();
            using (SqlCommand command = new SqlCommand(sql.ToString(), connection)) {
                command.CommandType = CommandType.Text;
                command.CommandTimeout = 300;
                returnCode = (string)command.ExecuteScalar();
                //Dispose();
            }
            //Dispose();
        }

我们的合同写了一堆code,以帮助SQL连接在APP_ code / sqlHelper.s文件。他们中有些人是这样的:

Our contractor wrote a bunch of code to help with SQL connections in an App_Code/sqlHelper.s file. Some of them are like this:

public static SqlDataReader GetDataReader(string sql, string connectionString, int connectionTime) {
        lock (_lock) {
            SqlConnection connection = null;
            try {
                connection = GetConnection(connectionString);
                //connection.Open();
                using (SqlCommand cmd = new SqlCommand(sql, connection)) {
                    cmd.CommandTimeout = connectionTime;
                    WriteDebugInfo("GetDataReader", sql);
                    return cmd.ExecuteReader(CommandBehavior.CloseConnection);
                }
            }
            catch (Exception e) {
                if (connection != null)
                    connection.Dispose();
                throw new DataException(sql, connectionString, e);
            }

        }
    }

如果有一些内存释放的地方?

Should there be some deallocation of memory somewhere?

推荐答案

的问题是,由于某些原因,你的DataReader没有被关闭。一个例外?该方法的用户不记得要关闭DataReader?

The problem is that, for some reason, your DataReader isn't being closed. An exception? The method user didn't remember to close the DataReader?

这是返回一个DataReader使用外其身离开关闭它外code的责任,所以没有保证,读者将被关闭的函数。如果您不关闭的读者,你不能重复使用在其被打开连接。

A function that returns a DataReader to be used outside its body leaves the responsibility of closing it to outer code, so there's no guarantee that the Reader will be closed. If you don't close the reader, you cannot reuse the connection in which it was opened.

所以从函数返回一个DataReader是一个非常糟糕的主意!

您可以看到这个问题的整个讨论here.

You can see a whole discussion on this subject here.

查找此功能( GetDataReader )的用法,并检查是否有保证,读者是越来越封闭。而且,最重要的是,没有任何可能性,这code重新进入,并使用相同的集合以打开一个新的DataReader之前首先被关闭。 (不要由CommandBehavior.CloseConnection误导。这只需要关闭连接时,DataReader的关闭的照顾......只有当你不失败,将其关闭)

Look for the usages of this function (GetDataReader), and check if there's guarantee that the reader is getting closed. And, most importantly, that there is no possibility that this code re-enters and uses the same collection to open a new DataReader before the first is closed. (Don't be mislead by the CommandBehavior.CloseConnection. This only takes care of closing the connection when the DataReader is closed... only if you don't fail to close it)