【问题标题】:Do I have to leave off the skip call in my query我是否必须在我的查询中停止跳过调用
【发布时间】:2013-08-02 21:23:16
【问题描述】:

我有一张大表,我想清除其中的旧记录。记录有一个字段“文件路径”。这里的“清除”是指将“文件路径”标记为空。问题是因为该表有数百万条记录,一次更新是不可能的。它炸毁了记忆。所以我的策略是每次获取 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 为空。然后在下一次运行时,它可能不会指向正确的块,因为我跳过了一个块。

我需要删除跳过部分吗?

【问题讨论】:

  • 这感觉更像是一个实用函数而不是客户端函数,最好作为存储过程 + 计划作业。

标签: c# linq


【解决方案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
}

【讨论】:

  • 你是对的,这里有两个查询。一个是“查询”,第二个是“q”,你的意思是忽略两者都跳过吗?要判断到达终点的位置,请使用 query.Count()
  • @Love 我添加了代码示例,展示了如何在循环中获取符合条件的前 N ​​个项目
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    相关资源
    最近更新 更多