我的问题

在我的日志(log)中,我看到在负载测试期间记录了一些System.OutOfMemory异常错误.它们来自Dapper查询.根据堆栈跟踪,调整列表大小时会发生错误.

堆栈跟踪的顶部

System.OutOfMemoyException:引发了类型为""System.OutOfMemoyException""的异常." 在System.Collections.Generic.List1.set_Capacity(Int32 value) at System.Collections.Generic.List1.AddWithResize(T项目中) 在C:\projects\dapper\Dapper\SqlMapper.Async.cs:line 442中的Dapper.SqlMapper.QueryAsync[T](IDbConnection CNN,输入有效类型,命令定义命令)

被调用的代码

const string sql = $@"
  SELECT [Column 1]
        ,[Column 2]
        ,[Column 3]
        ,[Column 4]
        ,[Column 5]
        ,[Column 6]
        ,[Column 7]
        ,[Column 8]
        ,[Column 9]
        ,[Column 10]
        ,[Column 11]
        ,[Column 12]
    FROM [MyDb].[MyTable]
    WHERE co = @CompanyId AND process = @Process
    ";

await using var connection = _dbConnectionProvider.Create(DbKey.MyDb);

var parameters = new { CompanyId = CompanyDbString(companyId), Process = process };
var command = new CommandDefinition(sql, parameters);
var results = await connection.QueryAsync<MyEntity>(command); // error happens here

return results;

有关正在加载的数据的一些信息

我查看了数据库,发现有问题的数据大小为141,846行.这些列没有什么"不寻常的"(没有巨大的文本块或类似的东西),只是一些合理的varchars、date time、int等.所有的varchars最大长度为100个字符.

为了避免不可避免的"您真的需要加载所有这些数据吗?"在萌芽状态下 comments :是的,我知道.

可能的解决方案是什么?

因此,正在加载的数据是一个相当大的数据集,但并不疯狂.我很惊讶它的内存用完了.我发现特别有趣的是,这一例外源于System.Collections.Generic.List1.set_Capacity(Int32 value).基于此,看起来错误是在列表调整其内部数组大小时发生的.

我对如何处理这个问题的第一个 idea 是对结果进行分页,就像这里建议的那样:https://stackoverflow.com/a/52212051

然而,我不确定这是否会奏效,因为它仍然依赖于添加到的列表.这是一个合理的担忧吗?如果是这样的话,首先获得计数并以此作为初始容量开始列出是不是一个好方法?

或者,是否存在一个比List更适合调整大小/内存的不同集合?

推荐答案

你需要做一个unbuffered Dapper query,然后把结果插入一个预先设定好大小的列表中.

var list = new List<MyEntity>(someBigSizeHere);
var command = new CommandDefinition(sql, parameters) { Buffered = false };
using var results = await connection.QueryAsync<MyEntity>(command);
list.AddRange(results);
return list;

请注意,在关闭连接之前,您必须确保完全阅读and disposeresults.

如果在此之后仍然出现内存不足的异常,那么您根本没有足够的数据.try 编译为64位并向您的系统添加更多的RAM.或者更好的是:重新思考你为什么需要这么多数据.

Csharp相关问答推荐

获取Windows和Linux上的下载文件夹

下拉图片点击MudBlazor

需要深入了解NpgSQL DateTimeOffset处理

什么是通过反射创建类的泛型接口方法的正确方法?

Blazor Foreach仅渲染最后一种 colored颜色

应用程序启动器,可 Select 物理屏幕

Azure函数中实体框架核心的依赖注入

如何将MongoDB序列化程序设置为内部对象属性

DateTime ToString()未以指定格式打印

为什么@rendermode Interactive Auto不能在.NET 8.0 Blazor中运行?

如何在onNext之前等待订阅者完成?

使用switch 类型模式时出现奇怪的编译器行为

Blazor Server/.NET 8/在初始加载时调用异步代码是否冻结屏幕,直到第一次异步调用完成?

如何在C# WinForm控件中使用Windows 10/11的黑暗主题?

并发表更新.EF核心交易

根据优先级整理合同列表

C#定时器回调对象上下文?

反序列化我以前使用System.Text.Json序列化的文件时出现异常

客户端/服务器RPC如何处理全局变量?

为什么Visual Studio 2022建议IDE0251将我的方法设置为只读?