我如何才能快速删除使用实体框架表中的所有行?
我目前使用:
var rows = from o in dataDb.Table
select o;
foreach (var row in rows)
{
dataDb.Table.Remove(row);
}
dataDb.SaveChanges();
但是,执行起来需要很长时间。
还有其他选择吗?
我如何才能快速删除使用实体框架表中的所有行?
我目前使用:
var rows = from o in dataDb.Table
select o;
foreach (var row in rows)
{
dataDb.Table.Remove(row);
}
dataDb.SaveChanges();
但是,执行起来需要很长时间。
还有其他选择吗?
当前回答
警告:以下仅适用于小表(考虑< 1000行)
这里是一个使用实体框架(而不是SQL)删除行的解决方案,因此它不是SQL Engine(R/DBM)特定的。
这里假设您这样做是为了测试或类似的情况。 要么
数据量过小或 表现不重要
简单地调用:
VotingContext.Votes.RemoveRange(VotingContext.Votes);
假设在此背景下:
public class VotingContext : DbContext
{
public DbSet<Vote> Votes{get;set;}
public DbSet<Poll> Polls{get;set;}
public DbSet<Voter> Voters{get;set;}
public DbSet<Candidacy> Candidates{get;set;}
}
为了让代码更整洁,你可以声明下面的扩展方法:
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();
我最近使用这种方法为每次测试用例运行清理我的测试数据库(它显然比每次从头创建数据库快,尽管我没有检查生成的删除命令的形式)。
为什么会变慢?
EF将得到所有的行(VotingContext.Votes) 然后会使用他们的id(不知道具体怎么做,没关系)删除他们。
因此,如果你正在处理大量的数据,你将杀死SQL server进程(它将消耗所有的内存),同样的事情对于IIS进程,因为EF将缓存所有数据与SQL server相同的方式。如果您的表包含大量数据,请不要使用此方法。
其他回答
在EFCore(我使用的版本是3.1),你可以使用以下方法删除所有行-
context.Database.ExecuteSqlRaw("TRUNCATE TABLE [TableName]");
EF Core 7.0通过添加批量更新和删除语义一次性解决了这个问题:
await dataDB.Table.ExecuteDeleteAsync();
注意,此语法立即执行底层(SQL)命令从表中删除数据。它不需要跟踪实体、标记实体以便删除,也不需要等待UpdateDatabase对数据库执行事务。
还要注意,默认情况下,单个事务中不会包含多个ExecuteDelete和ExecuteUpdate命令。但是,可以使用DbContext事务api在事务中包装这些命令。
下面的工作在SQLite数据库(使用实体框架)。
似乎清除所有db表的最快方法是使用context.Database。ExecuteSqlCommand(“一些SQL”),正如上面的一些注释所突出显示的那样。在这里,我将展示如何重置表的“索引”计数。
context.Database.ExecuteSqlCommand("delete from TableA");
context.Database.ExecuteSqlCommand("delete from sqlite_sequence where name='TableA'");//resets the autoindex
context.Database.ExecuteSqlCommand("delete from TableB");
context.Database.ExecuteSqlCommand("delete from sqlite_sequence where name='TableB'");//resets the autoindex
context.Database.ExecuteSqlCommand("delete from TableC");
context.Database.ExecuteSqlCommand("delete from sqlite_sequence where name='TableC'");//resets the autoindex
重要的一点是,如果在表中使用外键,则必须首先在父表之前删除子表,因此在删除过程中表的顺序(层次结构)很重要,否则可能会发生SQLite异常。
注意:var context = new YourContext()
使用SQL的TRUNCATE TABLE命令将是最快的,因为它操作的是表,而不是单个行。
dataDb.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
假设dataDb是一个DbContext(而不是ObjectContext),你可以包装它并像这样使用方法:
var objCtx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)dataDb).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
using (var context = new DataDb())
{
var ctx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext;
ctx.ExecuteStoreCommand("DELETE FROM [TableName] WHERE Name= {0}", Name);
}
or
using (var context = new DataDb())
{
context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}