You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向Data Table导入大量记录时触发System.OutOfMemoryException问题求助

嘿,我来帮你搞定这个System.OutOfMemoryException的问题!你遇到的情况太常见了——哪怕是64位机器,一次性把几十万甚至上百万条数据库记录全加载到内存里,再加上Entity Framework实例化实体、Json序列化的开销,内存很容易就爆掉。下面给你几个实用的解决方案,按优先级排序:

1. 优先用分页加载数据

这是最直接有效的方法,不要一次性把整个表的数据都ToList(),而是分批次返回。前端的Data Table本身就支持分页功能,你只需要后端接收页码和页大小参数,按需查询数据:

public ActionResult GetData(int page = 1, int pageSize = 1000)
{
    using (MVCPRACEntities db = new MVCPRACEntities())
    {
        // 先获取总记录数,方便前端做分页控件
        var totalRecords = db.AMSFR_APRR_INVOICE_HIST2.Count();
        
        // 分页查询:排序后跳过前面的记录,取当前页的数据
        var emplist = db.AMSFR_APRR_INVOICE_HIST2
                        .OrderBy(x => x.Id) // 必须排序才能用Skip/Take,不然分页结果会乱
                        .Skip((page - 1) * pageSize)
                        .Take(pageSize)
                        .ToList();
        
        // 返回数据和总条数,前端Data Table可以用这两个参数渲染分页
        return Json(new { data = emplist, total = totalRecords }, JsonRequestBehavior.AllowGet);
    }
}

这样每次只加载当前页的1000条数据(你可以调整pageSize),内存占用会直接降到原来的几十分之一甚至百分之一。

2. 只加载需要的字段

如果你的Data Table不需要展示表中所有字段,就别用SELECT *(Entity Framework默认会加载所有字段),只挑需要的字段查询,能进一步减少每条记录的内存开销:

var emplist = db.AMSFR_APRR_INVOICE_HIST2
                .Select(x => new 
                { 
                    x.InvoiceId, 
                    x.InvoiceDate, 
                    x.TotalAmount, 
                    x.VendorName 
                }) // 只取前端需要的字段
                .OrderBy(x => x.InvoiceId)
                .Skip((page - 1) * pageSize)
                .Take(pageSize)
                .ToList();
3. 检查项目的编译目标平台

别忽略这个细节!哪怕你的电脑是64位,如果项目的编译目标是32位(默认可能是Any CPU但勾选了「Prefer 32-bit」),程序运行时还是32位进程,内存上限只有2GB左右,很容易触发OOM。

解决步骤:

  • 右键你的项目 → 「属性」
  • 切换到「生成」标签页
  • 「平台目标」选择x64,取消勾选「Prefer 32-bit」
  • 重新编译运行
4. 用DataReader流式读取(适合超大数据量)

如果数据量特别大,分页都嫌麻烦,可以直接用DataReader流式读取数据,它不会一次性把所有数据加载到内存,而是读一条处理一条:

public ActionResult GetData()
{
    using (MVCPRACEntities db = new MVCPRACEntities())
    {
        var connection = db.Database.Connection;
        connection.Open();
        
        using (var cmd = connection.CreateCommand())
        {
            cmd.CommandText = "SELECT InvoiceId, InvoiceDate, TotalAmount, VendorName FROM AMSFR_APRR_INVOICE_HIST2";
            using (var reader = cmd.ExecuteReader())
            {
                DataTable dt = new DataTable();
                dt.Load(reader); // DataTable.Load也是流式处理,内存占用低
                return Json(dt, JsonRequestBehavior.AllowGet);
            }
        }
    }
}

这种方法跳过了Entity Framework的实体实例化过程,内存开销会小很多,但缺点是需要自己写SQL语句(或者用存储过程)。


内容的提问来源于stack exchange,提问作者Ashton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:36:55