【问题标题】:Foreach loop through table seems to load every row and run out of memoryForeach 循环遍历表似乎加载每一行并耗尽内存
【发布时间】:2014-07-21 07:20:34
【问题描述】:

我正在尝试使用 EF 版本 6.1.1 在 C# 中使用实体框架转储数据库表。 我希望 foreach 循环一次加载每一行,但它会逐渐加载每一行,然后内存不足。

foreach (Quote L in context.Quotes)
    sw.WriteLine(
        "INSERT INTO [dbo].[Quote] ([QuoteId], [BookId], [VerbTenseId], [Form], [Quotation]) VALUES (%1,%2,%3,N'%4',N'%5')", 
        L.QuoteId, L.BookId, L.VerbTenseId, L.Form, L.Quotation);

在上面的代码中,context 是已经初始化到我的数据库的 DatabaseContext,而 Quotes 是 Quote 记录的有效表。我正在尝试将每条记录转储到文件中进行备份。 显然(如前所述)我可以放弃实体框架并使用 DataReader 来迭代数据库表,但框架确实允许迭代太大而无法放入内存的表。

是否有一种优雅的方式(可能是上下文中某处的标志)允许这样做?

通常,结果集很小(几千),但在这种情况下它会达到数百万。

似乎有一些选项适用于以前版本的框架,但除非我误解,否则这些方法和标志不再存在。

这只是测试代码,不是常规的数据库备份。我不是在寻找更好的方式来表达我的代码。我正在寻找一种优雅的方式来使用 EF。如果 EF 只是缺少这种支持,那就是我的答案。

请不要乱用示例,只要回答是否有办法使用 EF 枚举数据库表,而无需将每一行都加载到内存中并保留在那里。我可以编写其他示例,并提供其他选项来实现数据库备份。这只是一个示例。

【问题讨论】:

  • 旁注:我希望你的引文中没有任何撇号。
  • 如果你需要备份你的数据库,为什么不使用真正的备份工具来备份数据库呢?
  • 这是使用字符串格式还是 ef 上下文?
  • EF 获取整个结果集并从中提取对象实例。它不是一次一行的游标。听起来您将不得不切换到原始 ADO.NET 并使用 DataReader。
  • 关闭更改跟踪可能会有所帮助。据我所知,假设您可以更改一条记录,然后调用 Save Changes,则上下文会保留每条记录。如果您不跟踪更改,它可能愿意在内存使用量攀升时释放缓存。

标签: entity-framework entity-framework-6 entity-framework-6.1


【解决方案1】:

我没有测试过,但是试试foreach (Quote L in context.Quotes.AsNoTracking()) {...}.AsNoTracking() 不应该将实体放入缓存中,所以我认为当它们超出范围时它们将被 GC 消耗。

另一种方法是实现批处理(选择前 N 个实体,处理,选择下一个前 N 个)。在这种情况下,请确保每次迭代都处理并创建新上下文,并在查询中使用正确的 OrderBy()。

【讨论】:

  • 是的,AsNoTracking() 对我有用!它拯救了我的一天。
猜你喜欢
  • 2012-02-08
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
相关资源
最近更新 更多