22

我在使用 LINQ-To-SQL 时遇到了一些关于内存使用的问题。我在 Windows 服务中使用它来进行一些处理,并且我正在循环访问从上下文中拉回的大量数据。是的 - 我知道我可以使用存储过程来做到这一点,但有一些原因表明这不是一个理想的解决方案。

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

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

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

4

5 回答 5

23

DataContext 跟踪它曾经获取的所有对象。在垃圾收集之前它不会释放它。此外,当它实现IDisposable时,您必须调用Dispose或使用该using语句。

这是正确的方法:

using(DataContext myDC = new DataContext)
{
  //  Do stuff
} //DataContext is disposed
于 2008-09-23T19:04:36.567 回答
15

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

于 2008-09-23T19:11:20.263 回答
7

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

看来您主要关心的是创建和处理一堆 DataContext 对象。这就是 linq2sql 的设计方式。DataContext 的生命周期很短。由于您要从数据库中提取大量数据,因此会占用大量内存是有道理的。通过分块处理数据,您走在正确的轨道上。

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

于 2008-09-23T19:25:09.123 回答
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
   }
}
于 2008-09-24T14:40:08.940 回答
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() 方法 - 无效

于 2016-09-16T11:51:35.450 回答