简体   繁体   English

Entity Framework Core RemoveRange() 在后台生成多个 DELETE 语句?

[英]Entity Framework Core RemoveRange() generates multiple DELETE statements under the hood?

For a long time I was believing that the method Context.RemoveRange() is optimized for multiple rows removal by using single DELETE statement, but today I noticed in my logs that actually per each of entity in the specified range there is executed a separate DELETE statement.很长一段时间以来,我一直相信 Context.RemoveRange() 方法通过使用单个 DELETE 语句针对多行删除进行了优化,但今天我注意到在我的日志中,实际上每个指定范围内的实体都执行了一个单独的 DELETE陈述。

Given the below example:鉴于以下示例:

// e.g. 200 entities
var entities = Context.MyTable.Where(x => x.ModificationDate < DateTime.Now).ToList();
Context.RemoveRange(entities);
        

Looking at the logs I've found that it is actually running multiple DELETE statements:查看日志我发现它实际上正在运行多个 DELETE 语句:

2021-08-17 16:07:46.726 +02:00 [INF] Executed DbCommand (3ms) [Parameters=[@p0='?' (DbType = 
Guid)], CommandType='"Text"', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [MyTable]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;

2021-08-17 16:07:46.731 +02:00 [INF] Executed DbCommand (0ms) [Parameters=[@p0='?' (DbType = 
Guid)], CommandType='"Text"', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [MyTable]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;

I've pasted logs related to only 2 records, but they keep repeating in the log file.我只粘贴了与 2 条记录相关的日志,但它们在日志文件中不断重复。

Is there any way I can make the RemoveRange() to run this as a single statement, eg DELETE FROM MyTable WHERE ID IN(1, 2)?有什么方法可以让 RemoveRange() 将其作为单个语句运行,例如 DELETE FROM MyTable WHERE ID IN(1, 2)?

Let me mention that I'm not asking for Context.MyTable.FromSqlRaw() or such.让我提一下,我不是要 Context.MyTable.FromSqlRaw() 之类的。 I'd like to know if this is somehow possible with RemoveRange().我想知道使用 RemoveRange() 是否可以做到这一点。

I have also tried the following:我还尝试了以下方法:

var ids = new [] { 1, 2 };
var entities = ids.Select(x=> new Entity() { Id = x });
Context.RemoveRange(entities);
        

But there is no difference.但是没有区别。

There are a lot of extensions that can make this operation effective.有很多扩展可以使这个操作有效。 I would suggest to use linq2db.EntityFrameworkCore (disclaimer: I'm one of the creators)我建议使用linq2db.EntityFrameworkCore (免责声明:我是创建者之一)

Then deleting become easy:然后删除变得容易:

var affected = Context.MyTable
   .Where(x => x.ModificationDate < DateTime.Now)
   .Delete();

Please take a look.请看一下。

"The number of statements that EF batches in a single roundtrip depends on the database provider being used. For example, performance analysis has shown batching to be generally less efficient for SQL Server when less than 4 statements are involved. Similarly, the benefits of batching degrade after around 40 statements for SQL Server, so EF Core will by default only execute up to 42 statements in a single batch, and execute additional statements in separate roundtrips." “单次往返中 EF 批处理的语句数量取决于所使用的数据库提供程序。例如,性能分析表明,当涉及少于 4 个语句时,批处理对于 SQL Server 的效率通常较低。同样,批处理的好处在 SQL Server 大约 40 条语句后降级,因此 EF Core 默认情况下在单个批处理中最多执行 42 条语句,并在单独的往返中执行其他语句。”

https://docs.microsoft.com/en-nz/ef/core/performance/efficient-updating https://docs.microsoft.com/en-nz/ef/core/performance/efficient-updating

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM