咨询区

  • 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 内,性能有所提升,不过确实只适合一些小表