我正在使用此库批量执行批量删除,如下所示:
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) 类型,并且出于性能原因对其进行了索引。
是否有任何其他库,我可以使用或调整此查询以使其工作得更快,因为目前性能绝对糟糕。
如果您准备使用存储过程,则可以在没有任何外部库的情况下执行此操作:
- 使用表值参数创建 sproc
@ids
- 为该表值参数定义 SQL 类型(假设是简单的 PK,只是一个
id
列) -
在程序使用
delete from table where id in (select id from @ids);
-
在应用程序中创建一个
DataTable
并填充以匹配 SQL 表 - 调用 sproc 时将数据表作为命令参数传递。
这个答案说明了这个过程。
任何其他选项都需要做与此相当的事情 - 或者效率较低的方法。
此处的任何 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();
}
但是,您可能需要批量循环,因为命令上允许的参数数量有上限。
如果你不介意额外的依赖关系,你可以使用 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较新的版本不能免费使用。