Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
类型'的例外情况;System.OutOfMemoryException';被扔了。C#使用IDataReader时_C#_Sql_Exception_Datareader_Using Statement - Fatal编程技术网

类型'的例外情况;System.OutOfMemoryException';被扔了。C#使用IDataReader时

类型'的例外情况;System.OutOfMemoryException';被扔了。C#使用IDataReader时,c#,sql,exception,datareader,using-statement,C#,Sql,Exception,Datareader,Using Statement,我有一个应用程序,其中我必须从数据库中获取大量数据。 因为它无法获取所有这些行(接近2000000行…),所以我将其分为几行,每次运行sql查询,每次只获取200000行 我使用DataTable输入所有数据(意味着所有2000000行都应该在那里) 头几次跑步很好。然后它会失败,并出现OutOfMemoryException 我的代码如下所示: private static void RunQueryAndAddToDT(string sql, string lastRowID, SqlCon

我有一个应用程序,其中我必须从数据库中获取大量数据。 因为它无法获取所有这些行(接近2000000行…),所以我将其分为几行,每次运行sql查询,每次只获取200000行

我使用DataTable输入所有数据(意味着所有2000000行都应该在那里)

头几次跑步很好。然后它会失败,并出现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);
        }
    }
在我看来,似乎读者一直在收集行,这就是为什么它只在第三轮或第二轮抛出异常

使用程序不应该在完成时清理内存吗? 什么可以解决我的问题

注意:我应该解释一下——我别无选择,只能将所有这些行都放到datatable中,因为我以后会对它们进行一些操作,而且行的顺序很重要,我不能拆分它,因为有时我必须将一些行的数据设置为一行,依此类推,所以我不能放弃


谢谢。

我认为您的内存不足,因为您不断添加到数据表中的所有行的数据表都太大了

在这种情况下,您可能需要尝试不同的模式


您不需要将行缓冲在列表(或数据表)中,而只需在行到达时生成可用的行即可吗?

您正在将数据副本存储到
dt
。您存储的内容太多,机器内存不足。因此,您几乎没有选择:

  • 增加可用内存
  • 减少正在检索的数据量
要增加可用内存,可以向机器添加物理内存。请注意,32位计算机上的.NET进程将无法访问超过2GB的内存(如果在
boot.ini
中启用3GB开关,则为3GB),因此,如果希望寻址更多内存,则可能需要切换到64位(计算机和进程)


检索更少的数据可能是一条出路。根据您试图实现的目标,您可能能够在数据的子集上执行任务(甚至可能在单个行上)。如果您正在执行某种聚合(例如,从数据生成摘要或报告),则可以使用。

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

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

但是,默认情况下,VisualStudio中对象的大小仍然限制为2GB。您可以创建几个组合大小大于2GB的阵列,但默认情况下无法创建大于2GB的阵列。如果仍然希望创建大于2GB的阵列,可以通过向app.config文件中添加以下代码来实现:

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


由于您使用的是
数据表
,所以让我来分享一下我使用数据表时遇到的一个随机问题。检查生成属性。我遇到数据表随机抛出内存不足异常的问题。事实证明,该项目的构建平台目标设置为
首选32位
。一旦我取消选择该选项,随机内存不足异常就消失了。

只是一条注释,如果数据大小增加一倍或三倍,该怎么办。必须有一个方法来只提取一些数据,否则以后可能会遇到很多麻烦。加载200万行是非常罕见的-大多数时候,这种方法是为了最大限度地减少加载的数据量。如果需要2M行,DataTable可能不是最好的模型(DataTable有开销)。我个人会将其加载到POCO模型中。使用并不能真正清除内存,也不会触发收集。另外:一个读者只有一小部分buffer@MarcGravell:这一点很好,但它使读卡器使用的内存符合收集条件,在这种情况下,如果结果没有存储在其他位置,则会阻止OOM。不,因为读卡器没有保存所有数据:这是一个流式API。对我来说很有用!谢谢非常感谢。为meI工作我使用32位应用程序,我试图从sql reader将1700000条记录添加到数据表中,因为它抛出了内存不足异常。再次使用上述解决方案后,它抛出了相同的错误。请建议我解决他的问题。