如何使用LINQ-To-SQL避免内存泄漏?

时间:2008-09-23 19:01:18

标签: database linq linq-to-sql memory-management memory-leaks

我在使用LINQ-To-SQL方面遇到了一些问题。我在Windows服务中使用它来进行一些处理,我正在循环浏览大量的数据,我正在从上下文中撤回。是的 - 我知道我可以通过存储过程来实现这一点,但有理由认为这不是理想的解决方案。

无论如何,我所看到的基本上是即使在我调用context.SubmitChanges()之后内存也没有被释放。所以我最终不得不做各种各样奇怪的事情,比如只追回100条记录,或创建几个上下文并让它们都做单独的任务。如果我保持相同的DataContext并稍后将其用于其他调用,它只会占用越来越多的内存。即使我在查询返回给我的“Clear()”数组上调用var tableRows,将其设置为null,并调用SYstem.GC.Collect() - 它仍然不释放内存。

现在我已经阅读了一些关于如何快速使用DataContexts并快速处理它们的内容,但似乎它们应该是强制上下文转储其所有数据(或其所有跟踪)的一种方式特定表的数据)在某一点确保内存是免费的。

任何人都知道哪些步骤可以保证释放内存?

5 个答案:

答案 0 :(得分:20)

DataContext跟踪它所获取的所有对象。在收集垃圾之前不会释放它。此外,在实施IDisposable时,您必须致电Dispose或使用using声明。

这是正确的方法:

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

答案 1 :(得分:15)

如果您不需要对象跟踪,请将 DataContext.ObjectTrackingEnabled 设置为 false 。如果你确实需要它,你可以使用反射来调用内部的 DataContext.ClearCache(),虽然你必须要知道,因为它的内部,它会在框架的未来版本中消失。据我所知,框架本身不使用它,但它 清除对象缓存。

答案 2 :(得分:6)

正如David指出的那样,你应该使用using块处理DataContext。

您的主要关注点似乎是创建和处理一堆DataContext对象。这就是linq2sql的设计方式。 DataContext意味着具有较短的生命周期。由于您从数据库中提取了大量数据,因此有大量内存使用是有意义的。通过以块为单位处理数据,您处于正确的轨道上。

不要害怕创建大量的DataContexts。它们旨在以这种方式使用。

答案 3 :(得分:3)

谢谢大家 - 我将查看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
   }
}

答案 4 :(得分:0)

我遇到了类似的问题。在我的例子中,帮助将 DataContext.ObjectTrackingEnabled 的属性设置为false。 但它只适用于迭代行的情况,如下所示:

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() - 没有效果