Zhe*_*nia 261 c# sql linq entity-framework
如何使用Entity Framework快速删除表中的所有行?
我目前正在使用:
var rows = from o in dataDb.Table
select o;
foreach (var row in rows)
{
dataDb.Table.Remove(row);
}
dataDb.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
但是,执行需要很长时间.
还有其他选择吗?
Ron*_*ijm 281
对于那些谷歌搜索并最终像我一样的人,这就是你目前在EF5和EF6中的表现:
context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
Run Code Online (Sandbox Code Playgroud)
假设上下文是一个 System.Data.Entity.DbContext
Ahm*_*ejo 196
警告:以下内容仅适用于小型表(想想<1000行)
这是一个使用实体框架(而不是SQL)来删除行的解决方案,因此它不是特定于SQL Engine(R/DBM)的.
这假设您正在进行测试或类似情况.或
只需致电:
VotingContext.Votes.RemoveRange(VotingContext.Votes);
Run Code Online (Sandbox Code Playgroud)
假设这个背景:
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;}
}
Run Code Online (Sandbox Code Playgroud)
对于更整洁的代码,您可以声明以下扩展方法:
public static class EntityExtensions
{
public static void Clear<T>(this DbSet<T> dbSet) where T : class
{
dbSet.RemoveRange(dbSet);
}
}
Run Code Online (Sandbox Code Playgroud)
然后上面变成:
VotingContext.Votes.Clear();
VotingContext.Voters.Clear();
VotingContext.Candidacy.Clear();
VotingContext.Polls.Clear();
await VotingTestContext.SaveChangesAsync();
Run Code Online (Sandbox Code Playgroud)
我最近使用这种方法来清理每个测试用例运行的测试数据库(这显然比每次从头重新创建数据库更快,尽管我没有检查生成的删除命令的形式).
为什么它会慢?
因此,如果您正在处理大量数据,您将终止SQL服务器进程(它将占用所有内存)和IIS进程同样的事情,因为EF将以与SQL服务器相同的方式缓存所有数据.如果您的表包含大量数据,请不要使用此项.
Rud*_*ser 87
使用SQL TRUNCATE TABLE
命令将是最快的,因为它在表上运行而不是在单个行上运行.
dataDb.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
Run Code Online (Sandbox Code Playgroud)
假设dataDb
是DbContext
(不是ObjectContext
),你可以包装它并使用如下方法:
var objCtx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)dataDb).ObjectContext;
objCtx.ExecuteStoreCommand("TRUNCATE TABLE [Table]");
Run Code Online (Sandbox Code Playgroud)
小智 39
var all = from c in dataDb.Table select c;
dataDb.Table.RemoveRange(all);
dataDb.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
Man*_*hra 36
using (var context = new DataDb())
{
var ctx = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext;
ctx.ExecuteStoreCommand("DELETE FROM [TableName] WHERE Name= {0}", Name);
}
Run Code Online (Sandbox Code Playgroud)
要么
using (var context = new DataDb())
{
context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}
Run Code Online (Sandbox Code Playgroud)
Bob*_*lth 23
EF Core 7.0通过添加批量更新和删除语义一劳永逸地解决了这个问题:
await dataDB.Table.ExecuteDeleteAsync();
Run Code Online (Sandbox Code Playgroud)
请注意,此语法立即执行基础 (SQL) 命令以从表中删除数据。它不会花时间跟踪实体、将其标记为删除以及等待UpdateDatabase
对数据库执行事务。
另请注意,默认情况下,多个ExecuteDelete
和ExecuteUpdate
命令不会包含在单个事务中。但是,可以按照正常方式使用 DbContext 事务 API 将这些命令包装在事务中。
Rob*_*ick 16
这可以避免使用任何sql
using (var context = new MyDbContext())
{
var itemsToDelete = context.Set<MyTable>();
context.MyTables.RemoveRange(itemsToDelete);
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
Omi*_*vid 14
没有Foreach,你可以做到这一点
dataDB.Table.RemoveRange(dataDB.Table);
dataDB.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
这将删除所有行
当我不得不处理一个特定的案例时,我遇到了这个问题:完全更新"叶子"表中的内容(没有指向它的FK).这涉及删除所有行并放置新行信息,它应该以事务方式完成(我不希望最终得到一个空表,如果插入因任何原因失败).
我尝试过这种public static void Clear<T>(this DbSet<T> dbSet)
方法,但没有插入新行.另一个缺点是整个过程很慢,因为行被逐个删除.
所以,我已经切换到TRUNCATE
接近,因为它更快,并且它也是ROLLBACKable.它也重置了身份.
使用存储库模式的示例
public class Repository<T> : IRepository<T> where T : class, new()
{
private readonly IEfDbContext _context;
public void BulkInsert(IEnumerable<T> entities)
{
_context.BulkInsert(entities);
}
public void Truncate()
{
_context.Database.ExecuteSqlCommand($"TRUNCATE TABLE {typeof(T).Name}");
}
}
// usage
DataAccess.TheRepository.Truncate();
var toAddBulk = new List<EnvironmentXImportingSystem>();
// fill toAddBulk from source system
// ...
DataAccess.TheRepository.BulkInsert(toAddBulk);
DataAccess.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
当然,如前所述,外键引用的表(TRUNCATE失败)不能使用此解决方案.
context.TableName.RemoveRange(context.TableName);
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
如果
using(var db = new MyDbContext())
{
await db.Database.ExecuteSqlCommandAsync(@"TRUNCATE TABLE MyTable"););
}
Run Code Online (Sandbox Code Playgroud)
原因
无法截断表“ MyTable”,因为它已被FOREIGN KEY约束引用。
我用这个:
using(var db = new MyDbContext())
{
await db.Database.ExecuteSqlCommandAsync(@"DELETE FROM MyTable WHERE ID != -1");
}
Run Code Online (Sandbox Code Playgroud)
小智 5
var data = (from n in db.users select n);
db.users.RemoveRange(data);
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
以下适用于 SQLite 数据库(使用实体框架)。
似乎清除所有数据库表的最快方法是使用context.Database.ExecuteSqlCommand("some 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
Run Code Online (Sandbox Code Playgroud)
重要的一点是,如果在表中使用外键,则必须先删除子表,再删除父表,因此删除时表的顺序(层次结构)很重要,否则可能会出现 SQLite 异常。
笔记:var context = new YourContext()