我在使用LINQ-To-SQL方面遇到了一些问题。我在Windows服务中使用它来进行一些处理,我正在循环浏览大量的数据,我正在从上下文中撤回。是的 - 我知道我可以通过存储过程来实现这一点,但有理由认为这不是理想的解决方案。
无论如何,我所看到的基本上是即使在我调用context.SubmitChanges()
之后内存也没有被释放。所以我最终不得不做各种各样奇怪的事情,比如只追回100条记录,或创建几个上下文并让它们都做单独的任务。如果我保持相同的DataContext
并稍后将其用于其他调用,它只会占用越来越多的内存。即使我在查询返回给我的“Clear()
”数组上调用var tableRows
,将其设置为null,并调用SYstem.GC.Collect()
- 它仍然不释放内存。
现在我已经阅读了一些关于如何快速使用DataContexts
并快速处理它们的内容,但似乎它们应该是强制上下文转储其所有数据(或其所有跟踪)的一种方式特定表的数据)在某一点确保内存是免费的。
任何人都知道哪些步骤可以保证释放内存?
答案 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() - 没有效果