1

这个问题与我以前的问题有关

这是我目前的代码

 IEnumerable<Shape> 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 太大了。我该如何预防?

4

4 回答 4

3

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

于 2009-06-23T18:57:37.880 回答
3

尝试使用InsertOnSubmit而不是InsertAllOnSubmit。然后像 Erich 所说的那样,以适当的时间间隔提交。

或者,如果您想分批进行,例如 5 个,请尝试使用Handcraftsmandtb 的解决方案来获取 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();
       }
   }
于 2009-06-23T18:58:44.320 回答
2

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

public static class IEnumerableExtensions
{
    public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
    {
        List<T> toReturn = new List<T>();
        foreach(var item in source)
        {
            toReturn.Add(item);
            if (toReturn.Count == max)
            {
                yield return toReturn;
                toReturn = new List<T>();
            }
        }
        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 文章很有用。

于 2009-06-23T20:37:22.547 回答
1

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

C#:将字符串数组划分为 N 个实例的最简洁方法

更新:不好,适用于数组。如果我以后有时间并且没有其他人提供任何东西,我会写下来......

于 2009-06-23T19:07:05.333 回答