6

我正在使用这个库来批量执行批量删除,如下所示:

  while (castedEndedItems.Any())
  {
    var subList = castedEndedItems.Take(4000).ToList();
    DBRetry.Do(() => EFBatchOperation.For(ctx, ctx.SearchedUserItems).Where(r => subList.Any(a => a == r.ItemID)).Delete(), TimeSpan.FromSeconds(2));
    castedEndedItems.RemoveRange(0, subList.Count);
    Console.WriteLine("Completed a batch of ended items");
  }

如您所见,我一次删除了一批 4000 个项目,并将它们作为参数传递给查询...

我正在使用这个库来执行批量删除:

https://github.com/MikaelEliasson/EntityFramework.Utilities

然而,这样的性能绝对是可怕的......我测试了几次应用程序并删除了 80000 条记录,例如它需要 40 分钟!?

我应该注意,我删除的那个参数 (ItemID) 是 varchar(400) 类型的,并且出于性能原因对其进行了索引....

是否有任何其他库我可以使用或调整此查询以使其更快地工作,因为目前性能绝对糟糕..:/

4

3 回答 3

6

如果您准备使用存储过程,那么您可以在没有任何外部库的情况下执行此操作:

  • 使用表值参数创建存储过程@ids
  • 为该表值参数定义 SQL 类型(只是id假设简单 PK 的列)
  • 在存储过程中使用

    delete from table where id in (select id from @ids);
    
  • 在您的应用程序中创建DataTable并填充以匹配 SQL 表

  • 调用 sproc 时将数据表作为命令参数传递。

这个答案说明了这个过程。

任何其他选择都需要做同样的事情——或者效率较低的事情。

于 2019-01-28T14:27:25.293 回答
4

这里的任何 EF 解决方案都可能会执行许多谨慎的操作。相反,我建议在循环中手动构建您的 SQL,例如:

using(var cmd = db.CreateCommand())
{
    int index = 0;
    var sql = new StringBuilder("delete from [SomeTable] where [SomeId] in (");
    foreach(var item in items)
    {
        if (index != 0) sql.Append(',');
        var name = "@id_" + index++;
        sql.Append(name);
        cmd.Parameters.AddWithValue(name, item.SomeId);            
    }
    cmd.CommandText = sql.Append(");").ToString();
    cmd.ExecuteNonQuery();
}

但是,您可能需要分批循环,因为命令允许的参数数量有上限。

于 2019-01-28T14:28:58.020 回答
2

如果你不介意额外的依赖,你可以使用 NuGet 包 Z.EntityFramework.Plus。

代码大致如下:

using Z.EntityFramework.Plus;
[...]
         using (yourDbContext context = new yourDbContext())
         {
              yourDbContext.yourDbSet.Where( yourWhereExpression ).Delete();
         }

它简单而高效。该文档包含有关性能的确切数字。

关于许可:据我所知,1.8 版有 MIT 许可:https ://github.com/zzzprojects/EntityFramework-Plus/blob/master/LICENSE 较新的版本不能免费使用。

于 2019-01-28T14:43:58.153 回答