0

我有以下方法用于循环遍历表,在每一行中更改一些值并将更改保存回数据库。为了让事情进展得更快,我以 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
4

4 回答 4

0

也许你可以试试这个:(我没有测试过)

db.SaveChanges()
For Each record In records
    record.dispose ''only if class table got a dispose method
Next
records.clear
records = Nothing
于 2010-11-04T11:23:41.967 回答
0

我绝不是 Linq to SQL 专家,但我的猜测是 DataContext 会缓存您已读取的所有行,因此您必须清空缓存或丢失对 DataContext 的引用。

于 2010-11-04T11:29:42.387 回答
0

存储库包含对其正在跟踪的每个实体的引用,因此当存储库处于活动状态并对其进行跟踪时,您将无法处置实体。这意味着您要么需要处置存储库,要么在完成处理后分离每个实体。

选项 1)如果“做一些工作”不影响您返回记录的顺序,您可以在 For 循环内移动创建 databaseEntities,并使用 using 块声明它。这应该导致每次在 for 循环中释放每个实体块

选项 2)如果您的操作本质上是并行的,并且您对一个“表”实体所做的操作对任何其他实体没有任何依赖关系,那么您可以在 db.SaveChanges 之后调用 databaseEntities.Detach(record),这将启用垃圾收集器以回收实体的空间。

查看您的代码,我怀疑其中任何一个都可以使用

于 2010-11-04T11:48:38.017 回答
0

如果您不需要更新实体,请使用MergeOption.NoTracking. 上下文将不再保留对实体的引用,也不会进行修复。

于 2010-11-04T14:40:42.373 回答