1

我有一张大桌子,我想在其中清除旧记录。记录有一个字段“文件路径”。这里的“清除”是指将“文件路径”标记为空。问题是因为该表有数百万条记录,一次更新是不可能的。它炸毁了记忆。所以我的策略是每次获取 2000 行并更新它们,然后继续处理下一个块。

我的查询:

int pageNumber = 0;
int pageSize = 2000;
bool hasHitEnd = false;

while (!hasHitEnd)
{
var size = pageNumber * pageSize;
var query = cdrContext.Mytable.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
    .OrderBy(c => c.TimeStationOffHook)
    .Skip(size)
    .Take(pageSize)
    .Select(c => new { c.FilePath, c.FileName })
    .ToList();
      var q = cdrContext.Mytable.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
         .OrderBy(c => c.TimeStationOffHook)
         .Skip(size)
         .Take(pageSize)
         .ToList();
foreach (var y in q)
{
   y.FilePath = null;
}
cdrContext.SaveChanges();
if (query.Count() < pageSize)
{
    hasHitEnd = true;
}
pageNumber++;

我对代码没有信心。因为更新数据后,FilePath 为空。然后在下一次运行中,当我跳过一个块时,它可能不会指向正确的块。

我需要删除跳过部分吗?

4

2 回答 2

1

您不需要跳过记录,因为更新后下一页将成为第一页(更新的项目将与您下次调用时的查询过滤器不匹配)。

// define query, but don't execute it
var query = cdrContext.Mytable.Where(c => c.FacilityID == facilityID && 
                                          c.FilePath != null && 
                                          c.TimeStationOffHook < oldDate)
                              .OrderBy(c => c.TimeStationOffHook)
                              .Take(pageSize);

List<Foo> itemsToUpdate = query.ToList(); // get first N items

while(itemsToUpdate.Any()) // all items updated
{
    // update items
    cdrContext.SaveChanges();
    itemsToUpdate = query.ToList(); // get first N items
}
于 2013-08-02T13:12:20.057 回答
1

无需跳过记录,后续页面将是您的第一页。此外,您不需要两次查询数据库,我看到您使用 query 和 q ,这是不必要的。只需使用 q 它将对性能有很大帮助。您可以删除以下代码

 if (query.Count() < pageSize)
 {
     hasHitEnd = true;
 }

如果 q.Count() == 0 将其替换为 q 中的记录数,那么您可以中断循环或设置 hasHitEnd = true;

于 2013-08-02T13:15:43.743 回答