Atl*_*e S 8 c# blob traversal out-of-memory entity-framework-core
我正在编写遍历大量图片数据的代码,并准备了一个大的增量块,其中包含所有压缩后用于发送的数据。
这是关于如何将这些数据作为示例
[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);
}
}
Run Code Online (Sandbox Code Playgroud)
使用此方法时,我会将所有内容处理到一个文件流中,并且希望在任何给定时间将其尽可能少地保留在内存中。
这样做够吗?
foreach(var b in context.Where(o => somefilters).AsNoTracking())
MessagePackSerializer.Serialize(stream, b);
Run Code Online (Sandbox Code Playgroud)
这是否仍将用所有blob记录填充内存,还是在我对枚举数进行迭代时将它们一一处理。它不使用任何ToList,仅使用枚举器,因此Entity Framework应该可以随时处理它,但是我不确定这是否是它的功能。
这里的任何实体框架专家都可以就如何正确处理提供一些指导。
一般来说,当您在实体上创建 LINQ 筛选器时,就像以代码形式编写 SQL 语句一样。它返回一个IQueryable尚未针对数据库实际执行的值。当您使用IQueryableorforeach调用迭代ToList()时,将执行 sql 并返回所有结果,并将其存储在内存中。
https://learn.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();
Run Code Online (Sandbox Code Playgroud)
现在,您已根据您的要求过滤了 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
}
Run Code Online (Sandbox Code Playgroud)
一旦你完成了大的blob,它就应该可以用于垃圾回收,并且你不应该耗尽内存。
显然,您可以感知检查 id 列表中的记录数量,或者您可以将元数据添加到第一个查询中,以帮助您决定如何处理它(如果您想完善这个想法)。
| 归档时间: |
|
| 查看次数: |
118 次 |
| 最近记录: |