Foreach循环表似乎加载每一行并耗尽内存

时间:2014-07-16 23:25:07

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

我正在尝试使用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枚举数据库表而不将每一行加载到内存中并保留在那里。我可以编写其他示例代码,并提供其他选项来实现数据库备份。这只是一个例子。

1 个答案:

答案 0 :(得分:2)

我还没有测试过,但请尝试foreach (Quote L in context.Quotes.AsNoTracking()) {...}.AsNoTracking()不应该将实体放在缓存中,因此我假设当它们超出范围时它们将被GC使用。

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