c# - 抛出类型为 'System.OutOfMemoryException' 的异常。使用 IDataReader 时的 C#

标签 c# sql exception datareader using-statement

我有一个应用程序,我必须在其中从数据库中获取大量数据。 由于它未能获取所有这些行(接近 2,000,000 行...),我中断了它,每次运行 sql 查询时每次都只获取 200,000 行。

我使用 DataTable 向其中输入所有数据(意思是 - 所有 2,000,000 行都应该在那里)。

前几次运行都很好。然后它因 OutOfMemoryException 而失败。

我的代码如下:

private static void RunQueryAndAddToDT(string sql, string lastRowID, SqlConnection conn, DataTable dt, int prevRowCount)
    {
        if (string.IsNullOrEmpty(sql))
        {
            sql = generateSqlQuery(lastRowID);
        }

        if (conn.State == ConnectionState.Closed)
        {
            conn.Open();
        }

        using (IDbCommand cmd2 = conn.CreateCommand())
        {
            cmd2.CommandType = CommandType.Text;
            cmd2.CommandText = sql;
            cmd2.CommandTimeout = 0;

            using (IDataReader reader = cmd2.ExecuteReader())
            {
                while (reader.Read())
                {
                    DataRow row = dt.NewRow();
                    row["RowID"] = reader["RowID"].ToString();
                    row["MyCol"] = reader["MyCol"].ToString();
                    ... //In one of these rows it returns the exception.

                    dt.Rows.Add(row);
                }
            }
        }

        if (conn != null)
        {
            conn.Close();
        }

        if (dt.Rows.Count > prevRowCount)
        {
            lastRowID = dt.Rows[dt.Rows.Count - 1]["RowID"].ToString();
            sql = string.Empty;
            RunQueryAndAddToDT(sql, lastRowID, conn, dt, dt.Rows.Count);
        }
    }

在我看来,好像读者一直在收集行,这就是为什么它只在第三轮或第二轮抛出异常。

Using 不应该在完成后清理内存吗? 什么可以解决我的问题?

注意:我应该解释一下 - 我别无选择,只能将所有这些行放到数据表中,因为我稍后会对它们进行一些操作,并且行的顺序很重要,我不能split它是因为有时候我要把一些行的数据取到一行中等等等等,所以我不能放弃。

谢谢。

最佳答案

检查您构建的是 64 位进程,而不是 32 位进程,这是 Visual Studio 的默认编译模式。为此,请右键单击您的项目,Properties -> Build -> platform target : x64。与任何 32 位进程一样,以 32 位编译的 Visual Studio 应用程序的虚拟内存限制为 2GB。

64 位进程没有此限制,因为它们使用 64 位指针,因此它们的理论最大地址空间为 16 exabytes (2^64)。实际上,Windows x64 将进程的虚拟内存限制为 8TB。内存限制问题的解决方案是在 64 位中编译。

但是,默认情况下,Visual Studio 中的对象大小仍限制为 2GB。您将能够创建多个组合大小大于 2GB 的数组,但默认情况下您不能创建大于 2GB 的数组。希望如果您仍然想创建大于 2GB 的数组,可以通过将以下代码添加到您的 app.config 文件来实现:

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

关于c# - 抛出类型为 'System.OutOfMemoryException' 的异常。使用 IDataReader 时的 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14020671/

相关文章:

java - 放入 Map 时出现非法状态异常

c# - 统一注册相互覆盖

c# - 无法确定类型为 “System.Data.Sqlite.SqliteFactory” 的提供程序工厂的提供程序名称

sql - PL/SQL 检查变量是否在立即执行的列表中

sql - 试图在 VBA 中解决 Object required 错误

java - 出现奇怪的 java.lang.NoClassDefFoundError 异常

c# - IOC/DI CaSTLeWindsor 每次都返回相同的实例

c# - 如何在返回 View 之前修改 Controller 中的查询字符串

mysql - sql语句中的减法

c++ - 如何在内部使用 C++ 异常并可以在旧平台上运行的 linux x64 上创建共享库对象?