【发布时间】:2020-03-09 00:27:21
【问题描述】:
我正在编写遍历大量图片数据的代码,准备一个包含所有图片数据的大增量块以供发送。
这是一个关于如何处理这些数据的示例
[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 应该能够随时随地处理它,但我不确定它是否这样做。
这里的任何实体框架专家都可以就如何正确处理提供一些指导。
【问题讨论】:
-
我不是 100% 确定,但我认为这会导致将单个查询发送到数据库,但是它会在 c# 端 1 接 1 处理它。(你可以用 sql 检查这个profiler)你可以改变你的循环并使用 skip 和 take 来确保你得到一个项目,但这不是 ef 的用途,所以我不确定你是否会找到最佳实践。
-
如果我理解正确,SqlDataReader 将在您迭代 Read() 时连接到数据库并获取部分。如果枚举器在这里的工作方式相同,那应该没问题。但是如果它缓冲所有,然后迭代,我们就有问题了。这里有人可以确认这是如何工作的吗?我希望它执行一个查询,但有一个到数据库的流连接,并在你处理数据时工作,一次处理和释放一个实体。
-
为什么不对代码进行内存分析?我们不能为你这样做。此外,由于未知的组件和周围的代码,这个问题很广泛/不清楚(如果不是为了赏金,就会被搁置)。 (比如,
stream来自哪里?)。最后,快速处理 SQL Server 文件流数据和流式处理需要一种超越 EF 的不同方法。
标签: c# entity-framework-core out-of-memory blob traversal