如何避免使用LINQ-To-SQL导致内存泄漏?
LINQ-To-SQL在内存使用方面一直存在一些问题。我在Windows服务中使用它来进行一些处理,并且正在遍历从上下文中拉回的大量数据。是的,我知道我可以使用存储过程来做到这一点,但是出于某些原因,这不是一个理想的解决方案。
无论如何,我基本上看到的是即使调用context.SubmitChanges()
也不会释放内存。因此,我最终不得不做各种奇怪的事情,例如一次只能拉回100条记录,或者创建多个上下文并使它们全部执行单独的任务。如果我保持相同的DataContext
并稍后将其用于其他调用,它将消耗越来越多的内存。即使我在查询返回给我的" var tableRows"数组上调用" Clear()",将其设置为null,然后调用" SYstem.GC.Collect()",它仍然不会释放内存。
现在,我已经阅读了一些有关如何快速使用" DataContexts"并快速处理它们的信息,但是似乎它们应该是一种强制上下文转储其所有数据(或者特定表的所有跟踪数据)的方式。 ),以确保内存可用。
有人知道哪些步骤可以保证释放内存吗?
解决方案
DataContext跟踪它曾经获取的所有对象。直到垃圾被收集,它才会释放它。同样,当它实现IDisposable时,必须调用Dispose或者使用using语句。
这是正确的方法:
using(DataContext myDC = new DataContext) { // Do stuff } //DataContext is disposed
如果不需要对象跟踪,请将DataContext.ObjectTrackingEnabled设置为false。如果确实需要它,则可以使用反射来调用内部DataContext.ClearCache(),尽管我们必须知道,由于它是内部的,因此它会在框架的将来版本中消失。据我所知,框架本身不使用它,但是确实清除了对象缓存。
正如David指出的那样,我们应该使用using块处理DataContext。
似乎我们主要关心的是创建和处置一堆DataContext对象。这就是linq2sql的设计方式。 DataContext的生命周期较短。由于我们要从数据库中提取大量数据,因此有大量的内存使用是有意义的。通过分块处理数据,我们将走上正确的道路。
不要害怕创建大量的DataContext。它们被设计为以这种方式使用。
谢谢大家,我将检查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 } }