咨询区
- Zhenia:
在 Entity Framework 中,如何快速高效的删除表中的所有行?
我目前是这样写的。
var rows = from o in dataDb.Table
select o;
foreach (var row in rows)
{
dataDb.Table.Remove(row);
}
dataDb.SaveChanges();
但这种做法,测试下来太耗费时间了,请问有什么更高效的做法吗?
回答区
- Ahmed Alejo:
警告:下面的做法仅适合那些小表操作 (?<1000)
这里我采用的是通过 EF 去删除表记录,而不是直接使用 sql,所以此种删除方式适合所有 EF 支持的 RDBM
,声明一下,如果你的表数据很小,或者你不在乎性能,可以简单如下调用。
VotingContext.Votes.RemoveRange(VotingContext.Votes);
为了让代码更干净简洁,可以专门定义一个 扩展方法
。
public static class EntityExtensions
{
public static void Clear<T>(this DbSet<T> dbSet) where T : class
{
dbSet.RemoveRange(dbSet);
}
}
接下来代码意图就明显了。
VotingContext.Votes.Clear();
VotingContext.Voters.Clear();
VotingContext.Candidacy.Clear();
VotingContext.Polls.Clear();
await VotingTestContext.SaveChangesAsync();
- Rudi Visser:
最快的方式当然是使用 SQL 的 TRUNCATE TABLE
,它是直接针对表操作而不是单独的行。
dataDb.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
如果你用的是 EFCore 3.1,可以使用下面的语句清空所有行。
context.Database.ExecuteSqlRaw("TRUNCATE TABLE [TableName]");
点评区
其实这是在 EF 操作中经常会遇到的一个问题,通常的做法也就上面这两种。
- 想更加通用,不考虑性能,采用 EF 直接操作,生成的 sql 大概如下。
static void Main(string[] args)
{
PYZ_LEntities entities = new PYZ_LEntities();
entities.Database.Log = Console.WriteLine;
entities.Color.RemoveRange(entities.Color);
entities.SaveChanges();
Console.ReadLine();
}
监控到 sql:
Opened connection at 2021/4/5 22:09:12 +08:00
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[ColorName] AS [ColorName],
[Extent1].[ColorCode] AS [ColorCode],
[Extent1].[IsDelete] AS [IsDelete]
FROM [dbo].[Color] AS [Extent1]
-- Executing at 2021/4/5 22:09:12 +08:00
-- Completed in 5 ms with result: SqlDataReader
Closed connection at 2021/4/5 22:09:12 +08:00
Opened connection at 2021/4/5 22:09:12 +08:00
Started transaction at 2021/4/5 22:09:12 +08:00
DELETE [dbo].[Color]
WHERE ([ID] = @0)
-- @0: '1' (Type = Int32)
-- Executing at 2021/4/5 22:09:12 +08:00
-- Completed in 1 ms with result: 1
DELETE [dbo].[Color]
WHERE ([ID] = @0)
-- @0: '2' (Type = Int32)
-- Executing at 2021/4/5 22:09:12 +08:00
-- Completed in 0 ms with result: 1
DELETE [dbo].[Color]
WHERE ([ID] = @0)
-- @0: '3' (Type = Int32)
-- Executing at 2021/4/5 22:09:12 +08:00
-- Completed in 0 ms with result: 1
Committed transaction at 2021/4/5 22:09:12 +08:00
Closed connection at 2021/4/5 22:09:12 +08:00
从输出信息看,清空操作采用的是将所有的sql拼在一个 Transaction
内,性能有所提升,不过确实只适合一些小表