Вопрос

У меня возникли некоторые проблемы с LINQ-To-SQL, связанные с использованием памяти.Я использую его в службе Windows для некоторой обработки и просматриваю большой объем данных, которые извлекаю из контекста.Да, я знаю, что мог бы сделать это с помощью хранимой процедуры, но есть причины, по которым это было бы далеко не идеальным решением.

В любом случае, я вижу, что в основном память не освобождается даже после того, как я звоню context.SubmitChanges().В итоге мне приходится делать всякие странные вещи, например извлекать только 100 записей за раз или создавать несколько контекстов и заставлять их выполнять отдельные задачи.Если я оставлю то же самое DataContext и использовать его позже для других вызовов, он просто съедает все больше и больше памяти.Даже если я позвоню Clear() на "var tableRows"массив, который мне возвращает запрос, установим для него значение null и вызовем SYstem.GC.Collect() - память все равно не освобождается.

Теперь я прочитал кое-что о том, как следует использовать DataContexts быстро и быстро избавиться от них, но похоже, что это должен быть способ заставить контекст сбросить все свои данные (или все данные отслеживания для конкретной таблицы) в определенный момент, чтобы гарантировать, что память свободна.

Кто-нибудь знает, какие шаги гарантируют освобождение памяти?

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

Решение

Если вам не нужен набор отслеживания объектов DataContext.ObjectTrackingEnabled к ЛОЖЬ.Если вам это нужно, вы можете использовать отражение для вызова внутреннего DataContext.ClearCache(), хотя вы должны знать, что, поскольку он является внутренним, он может исчезнуть в будущей версии платформы.И, насколько я могу судить, сам фреймворк его не использует, но он делает очистить кэш объектов.

Другие советы

DataContext отслеживает все объекты, которые он когда-либо извлекал.Он не выпустит это, пока не будет собран мусор.Кроме того, по мере реализации IDisposable, ты должен позвонить Dispose или используйте using заявление.

Это правильный путь:

using(DataContext myDC = new DataContext)
{
  //  Do stuff
} //DataContext is disposed

Как указывает Дэвид, вам следует избавиться от DataContext, используя блок using.

Кажется, ваша главная задача — создание и удаление множества объектов DataContext.Вот как устроен linq2sql.DataContext должен иметь короткий срок службы.Поскольку вы извлекаете много данных из БД, имеет смысл использовать много памяти.Вы находитесь на правильном пути, обрабатывая данные порциями.

Не бойтесь создавать массу DataContexts.Они созданы для такого использования.

Спасибо, ребята, я проверю метод ClearCache.Просто для пояснения (для будущих читателей): ситуация, в которой я получал использование памяти, была примерно такой:

using(DataContext context = new DataContext())
{
   while(true)
   {
      int skipAmount = 0;
      var rows = context.tables.Select(x => x.Dept == "Dept").Skip(skipAmount).Take(100);

      //break out of loop when out of rows

      foreach(table t in rows)
      {
         //make changes to t   
      }

      context.SubmitChanges();
      skipAmount += rows.Count();

      rows.Clear();
      rows = null;

      //at this point, even though the rows have been cleared and changes have been
      //submitted, the context is still holding onto a reference somewhere to the
      //removed rows.  So unless you create a new context, memory usuage keeps on growing
   }
}

Я только что столкнулся с похожей проблемой.В моем случае помогло установить свойства DataContext.ObjectTrackingEnabled к ложному.Но это работает только в случае перебора строк следующим образом:

using (var db = new DataContext())
{
    db.ObjectTrackingEnabled = false;
    var documents = from d in db.GetTable<T>()
                     select d;
    foreach (var doc in documents)
    {
        ...
    }
}

Если, например, в запросе использовать методы ToArray() или ToList() - никакого эффекта

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