gpt4 book ai didi

c# - 实体数据查询和内存泄漏

转载 作者:太空狗 更新时间:2023-10-30 00:08:20 25 4
gpt4 key购买 nike

我在一个循环中下载了很多数据,但是在一些操作之后我删除了它们,但是我看到的是内存分配增长非常快,几秒钟和1GB,所以如何在每次迭代之后清除呢?

    using (var contex = new DB)
{

var inputs = contex.AIMRInputs.Where(x => x.Input_Type == 1);

foreach (var input in inputs)
{
var data = contex.Values.Where(x => x.InputID == input.InputID).OrderBy(x => x.TimeStamp).ToList();

if (data.Count == 0) continue;
foreach (var value in data)
{
Console.WriteLine(Value.property);
}
data.Clear();


}
}

最佳答案

您可以做的第一件事是禁用更改跟踪,因为您不会更改代码中的任何数据。这样可以防止加载的对象附加到上下文:
对于DbContext(ef>=4.1):

var inputs = contex.AIMRInputs.AsNoTracking()
.Where(x => x.Input_Type == 1);

以及:
var data = contex.Values.AsNoTracking()
.Where(x => x.InputID == input.InputID)
.OrderBy(x => x.TimeStamp)
.ToList();

编辑
对于ef 4.0,您可以保持查询原样,但在 using块的前两行中添加以下内容:
contex.AIMRInputs.MergeOption = MergeOption.NoTracking;
contex.Values.MergeOption = MergeOption.NoTracking;

这将禁用 ObjectContext的更改跟踪。
编辑2
…特别是引用@james reategui下面的评论,即 AsNoTracking减少了内存占用:
这通常是正确的(比如在这个问题的模型/查询中),但并不总是正确的!实际上使用 AsNoTracking可能会对内存使用产生反作用。
当对象在内存中具体化时, AsNoTracking会做什么?
第一:它不会将实体附加到上下文,因此不会在上下文的状态管理器中创建条目。这些条目消耗内存。当使用poco时,条目包含实体的属性值的快照(当它第一次加载/附加到上下文时)——基本上是除了对象本身之外的所有(标量)属性的副本。因此,当不应用 AsNoTracking时,消耗的内存大约是对象大小的两倍。
第二:另一方面,当实体没有连接到上下文时,ef不能利用键值和对象引用标识之间的标识映射的优势。这意味着具有相同键的对象将被物化多次,这将消耗额外的内存,而不使用 AsNoTrackingef将确保每个键值仅物化一次实体。
当相关实体被加载时,第二点变得特别重要。简单示例:
例如,我们有一个 Order和一个 Customer实体,一个订单有一个客户 Order.Customer。假设 Order对象的大小为10字节, Customer对象的大小为20字节。现在我们运行以下查询:
var orderList = context.Orders
.Include(o => o.Customer).Take(3).ToList();

假设所有3个加载的订单都分配了相同的客户。因为我们没有禁用跟踪ef将实现:
3个订单对象=3x10=30字节
1个customer对象=1x20=20字节(因为上下文识别所有3个订单的customer是相同的,所以它只实现一个customer对象)
原始值为3x10=30字节的三阶快照条目
1个原始值为1x20=20字节的客户快照条目
总和:100字节
(为简单起见,我假设具有复制属性值的上下文条目的大小与实体本身的大小相同。)
现在,我们在禁用更改跟踪的情况下运行查询:
var orderList = context.Orders.AsNoTracking()
.Include(o => o.Customer).Take(3).ToList();

具体化的数据是:
3个订单对象=3x10=30字节
3(!)customer objects=3x20=60字节(没有标识映射=每个键有多个对象,所有三个customer对象都有相同的属性值,但它们仍然是内存中的三个对象)
没有快照条目
总和:90字节
因此,在这种情况下,使用 AsNoTracking查询将消耗10字节的内存。
现在,对5个订单进行相同的计算( Take(5)),同样,所有订单都有相同的客户:
AsNoTracking
5个订单对象=5x10=50字节
1个客户对象=1x20=20字节
原始值为5x10=50字节的5阶快照条目
1个原始值为1x20=20字节的客户快照条目
总和:140字节
使用 AsNoTracking
5个订单对象=5x10=50字节
5(!)客户对象=5x20=100字节
没有快照条目
总和:150字节
这一次使用 AsNoTracking的开销要高出10个字节。
上面的数字很粗略,但在某个地方使用 AsNoTracking可能需要更多内存。
使用 AsNoTracking与不使用 AsNoTracking之间的内存消耗差异在很大程度上取决于查询、模型中的关系以及查询加载的具体数据。例如: AsNoTracking当上面例子中的订单(或大部分订单)有不同的客户时,内存消耗总是更好的。
结论: AsNoTracking主要用于提高查询性能,而不是内存使用。在许多情况下,它也会消耗更少的内存。但是如果一个特定的查询需要使用 AsNoTracking的更多内存,不要惊讶。最后,您必须测量内存占用率,以便做出支持或反对 的可靠决定。

关于c# - 实体数据查询和内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9843422/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com