gpt4 book ai didi

c# - Entity Framework Core 在无内存溢出的情况下遍历大 blob 数据,最佳实践

转载 作者:行者123 更新时间:2023-12-04 08:50:38 24 4
gpt4 key购买 nike

我正在编写遍历大量图片数据的代码,准备一个包含所有压缩以发送的大增量块。

这是一个关于如何处理这些数据的示例

[MessagePackObject]
public class Blob : VersionEntity
{
[Key(2)]
public Guid Id { get; set; }
[Key(3)]
public DateTime CreatedAt { get; set; }
[Key(4)]
public string Mediatype { get; set; }
[Key(5)]
public string Filename { get; set; }
[Key(6)]
public string Comment { get; set; }
[Key(7)]
public byte[] Data { get; set; }
[Key(8)]
public bool IsTemporarySmall { get; set; }
}

public class BlobDbContext : DbContext
{
public DbSet<Blob> Blob { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blob>().HasKey(o => o.Id);
}
}

使用它时,我将所有内容都处理成一个文件流,并且我希望在任何给定时间都尽可能少地保留在内存中。

这样做就够了吗?
foreach(var b in context.Where(o => somefilters).AsNoTracking())
MessagePackSerializer.Serialize(stream, b);

这是否仍会用所有 blob 记录填满内存,还是会在我迭代枚举器时将它们一一处理。它不使用任何 ToList,只使用枚举器,因此 Entity Framework 应该能够随时随地处理它,但我不确定这是否是它的作用。

这里的任何 Entity Framework 专家都可以就如何正确处理此问题提供一些指导。

最佳答案

通常,当您在实体上创建 LINQ 过滤器时,就像以代码形式编写 SQL 语句一样。它返回一个 IQueryable没有实际对数据库执行。当您遍历 IQueryable 时与 foreach或调用 ToList()然后执行sql并返回所有结果,并存储在内存中。

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/language-reference/query-execution

虽然 EF 可能不是纯性能的最佳选择,但有一种相对简单的方法来处理这个问题,而无需过多担心内存使用:

考虑以下

var filteredIds = BlobDbContext.Blobs
.Where(b => b.SomeProperty == "SomeValue")
.Select(x => x.Id)
.ToList();

现在您已经根据您的要求过滤了 Blob,并对数据库执行了此操作,但只返回了内存中的 Id 值。

然后
foreach (var id in filteredIds)
{
var blob = BlobDbContext.Blobs.AsNoTracking().Single(x => x.Id == id);
// Do your work here against a single in-memory blob
}

完成后,大 blob 应该可用于垃圾收集,并且不应耗尽内存。

显然,您可以通过感知检查 id 列表中的记录数,或者您可以将元数据添加到第一个查询中,以帮助您决定如何处理它,如果您想完善这个想法。

关于c# - Entity Framework Core 在无内存溢出的情况下遍历大 blob 数据,最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58833183/

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