使用IEnumerable 和Linq-To-Sql时如何防止内存溢出?

这个问题与我之前的一个问题有关

这是我目前的代码

IEnumerable Get() { while(//get implementation yield return new Shape(//... } void Insert() { var actual = Get(); using (var db = new DataClassesDataContext()) { db.Shapes.InsertAllOnSubmit(actual); db.SubmitChanges(); } } 

我的内存溢出,因为IEnumerable太大了。 我该如何预防呢?

尝试使用InsertOnSubmit而不是InsertAllOnSubmit 。 然后像Erich说的那样以适当的间隔投入。

或者,如果你想分批进行5次,请尝试使用Handcraftsman或dtb的解决方案获取IEnumerable的IEnumerable。 例如,使用dtb的Chunk:

  var actual = Get(); using (var db = new DataClassesDataContext()) { foreach(var batch in actual.Chunk(5)) { db.Shapes.InsertAllOnSubmit(batch); db.SubmitChanges(); } } 

一种选择是将其分成多个批次。 创建Shape对象的临时缓冲区,迭代直到填充它或从枚举器中运行,然后执行InsertBatchOnSubmit

使用以下扩展方法将输入分解为适当大小的子集

 public static class IEnumerableExtensions { public static IEnumerable> InSetsOf(this IEnumerable source, int max) { List toReturn = new List(); foreach(var item in source) { toReturn.Add(item); if (toReturn.Count == max) { yield return toReturn; toReturn = new List(); } } if (toReturn.Any()) { yield return toReturn; } } } 

然后坚持子集

 void Insert() { var actual = Get(); using (var db = new DataClassesDataContext()) { foreach (var set in actual.InSetsOf(5)) { db.Shapes.InsertAllOnSubmit(set); db.SubmitChanges(); } } } 

您可能还会发现有关InsertOnSubmit()和InsertAllOnSubmit()的这篇MSDN文章很有用。

有关从IEnumerable获取批量项目的简洁方法,请参阅:

C#:将字符串数组分成N个实例的最简洁方法N个项目长

更新:不好,适用于arrays。 如果我有一段时间以后没有其他人提供过什么,我会把它写下来……