Как предотвратить переполнение памяти при использовании IEnumerable < > и Linq-To-Sql?

StackOverflow https://stackoverflow.com/questions/1034429

Вопрос

Этот вопрос связан с моим предыдущим вопросом

Это мой текущий код

 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 слишком велик. Как мне это предотвратить?

Это было полезно?

Решение

Попробуйте использовать InsertOnSubmit вместо < a href = "http://msdn.microsoft.com/en-us/library/bb763476(VS.100).aspx" rel = "nofollow noreferrer"> InsertAllOnSubmit . А затем фиксируйте через определенные промежутки времени, как сказал Эрих.

Или, если вы хотите сделать это, например, партиями 5, попробуйте Handcraftsman's или dtb's решения для получения IEnumerable's IEnumerable. Например, с помощью dtb's 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<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();
        }
    }
}

Вы также можете найти эта статья MSDN о InsertOnSubmit () против InsertAllOnSubmit () может быть полезной.

Для удобного способа получить партии элементов из IEnumerable, смотрите это:

C #: самый простой способ разделить строковый массив на N экземпляров длиной N элементов

Обновление: не очень хорошо, это работает на массивах. Если у меня будет какое-то время спустя и никто ничего не предоставит, я напишу это ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top