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

使用SQLite DataReader读取数据时触发OutOfMemoryException求助

问题根源

就算设置了CommandBehavior.SequentialAccess,直接用dataReader["ColumnName"].ToString()或GetString()读取12MB级的大文本列时,还是会一次性把整个字段的字节数组加载到内存再转成字符串,多次累积后就触发了OutOfMemoryException。

解决步骤&代码修改

1. 先修正批量读取逻辑(如果是读20条记录)

原ExecuteReader<T>返回单个T,没法逐行释放内存,改成返回IEnumerable<T>,用yield return逐行处理:

public static IEnumerable<T> ExecuteReader<T>(string commandText, IEnumerable<QueryParameter> parameters, Func<IDataReader, T> parserMethod)
{
    using (var command = SqliteDbProvider.FetchSqliteDbConnection().CreateCommand())
    {
        AddQueryInCommand(commandText, parameters, command);
        using (var dataReader = command.ExecuteReader(CommandBehavior.SequentialAccess))
        {
            // 逐行读,处理完一条就返回,避免内存堆积
            while (dataReader.Read())
            {
                yield return parserMethod(dataReader);
            }
        }
    }
}

2. 用流分段读取大文本字段

替换原来直接读取列的方式,用GetStream()获取字段流,通过缓冲区分段构建字符串,避免一次性加载全部数据:

private static IResourceDefinition GetResourceDefinition(IDataReader dataReader)
{
    // 先拿列索引,比用列名高效
    int resourceDefColIndex = dataReader.GetOrdinal("ResourceDefinition");
    int xmlDefColIndex = dataReader.GetOrdinal("XmlDefinition");

    // 小字段正常读取
    JObject jsonObject = JObject.Parse(dataReader.GetString(resourceDefColIndex));

    // 大Xml字段分段读取
    string xmlDefinition;
    const int bufferSize = 8192; // 8KB缓冲区,可根据内存情况调整
    using (var stream = dataReader.GetStream(xmlDefColIndex))
    using (var streamReader = new StreamReader(stream, Encoding.UTF8))
    {
        StringBuilder sb = new StringBuilder();
        char[] buffer = new char[bufferSize];
        int readCount;

        while ((readCount = streamReader.Read(buffer, 0, bufferSize)) > 0)
        {
            sb.Append(buffer, 0, readCount);
        }
        xmlDefinition = sb.ToString();
    }

    // 构建返回对象(示例)
    return new ResourceDefinition
    {
        ResourceData = jsonObject,
        XmlDefinition = xmlDefinition
    };
}

3. 注意事项

  • 用SequentialAccess必须按查询结果的列顺序读取,不能跳着读(比如先读XmlDefinition再读ResourceDefinition),当前代码的顺序是对的。
  • 如果不需要完整的XmlDefinition字符串,直接对流做解析处理(比如用XmlReader直接读流),能更省内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:19:59