我有以下循环表的方法,在每一行中更改一些值并将chages保存回数据库。为了让事情变得更快,我将以10,000行的形式获取数据。这是一张大表,里面有超过2500万条记录。
问题是我的应用程序似乎没有释放任何内存。我尝试将records
变量重新声明为nothing
或明确地对垃圾收集器进行调用,但内存保留在那里。
运行内置的VS10探查器我可以看到罪魁祸首是system.linq.enumerable.tolist()
方法,它占用了超过98%的内存。如何在致电saveChanges
后释放内存?
db = New databaseEntities
Dim size = 25000000
Dim stepSize = 10000
For i = 0 to size Step stepSize
Dim sql = (From A In db.table).OrderBy(Function(A) A.Column).Skip(i).Take(stepSize)
Dim records As New List(Of table)
records = sql.ToList
For Each record In records
'do some work
Next
db.SaveChanges()
records = Nothing
GC.Collect()
Next
答案 0 :(得分:0)
也许你可以试试这个:(我没试过它)
db.SaveChanges()
For Each record In records
record.dispose ''only if class table got a dispose method
Next
records.clear
records = Nothing
答案 1 :(得分:0)
我绝不是Linq to SQL专家,但我的猜测是DataContext会缓存您已读取的所有行,因此您必须清空缓存或丢失对DataContext的引用。
答案 2 :(得分:0)
存储库包含对其正在跟踪的每个实体的引用,因此在存储库处于活动状态并跟踪它时,您将无法处置实体。这意味着您需要处理存储库,或者在完成处理后分离每个实体。
选项1)如果“做一些工作”不影响您返回记录的顺序,您可以在For循环中移动databaseEntities的创建,并使用using块声明它。这应该导致每次实体块都在for循环中释放
选项2)如果您的操作基本上是并行的,并且您对一个“表”实体的操作与任何其他实体没有任何依赖关系,那么您可以在db.SaveChanges之后调用databaseEntities.Detach(record),这将使垃圾收集器能够回收实体的空间。
查看您的代码,我怀疑其中任何一个都可以使用
答案 3 :(得分:0)
如果您不需要更新实体,请使用MergeOption.NoTracking
。上下文将不再保留对实体的引用,也不会进行修复。