dbContext.Database.ExecuteSqlCommand("delete from MyTable");
(No kidding.)
The problem is that EF doesn't support any batch commands and the only way to delete all entities in a set using no direct DML would be:
foreach (var entity in dbContext.MyEntities)
dbContext.MyEntities.Remove(entity);
dbContext.SaveChanges();
Or maybe a litte bit cheaper to avoid loading full entities:
foreach (var id in dbContext.MyEntities.Select(e => e.Id))
{
var entity = new MyEntity { Id = id };
dbContext.MyEntities.Attach(entity);
dbContext.MyEntities.Remove(entity);
}
dbContext.SaveChanges();
But in both cases you have to load all entities or all key properties and remove the entities one by one from the set. Moreover when you call SaveChanges EF will send n (=number of entities in the set) DELETE statements to the database which also get executed one by one in the DB (in a single transaction).
So, direct SQL is clearly preferable for this purpose as you only need a single DELETE statement.
public static class Extensions
{
public static void DeleteAll<T>(this DbContext context)
where T : class
{
foreach (var p in context.Set<T>())
{
context.Entry(p).State = EntityState.Deleted;
}
}
}
As the accepted answer only mentions about the method below:
context.Database.ExecuteSqlCommand("delete from MyTable");
and rather gives alternatives to it, I've managed to write a method, which you can use to avoid loading all entities, then looping through them and use ExecuteSqlCommand instead.
Assuming using unit of work, where context is DbContext:
using System.Data.Entity.Core.Objects;
using System.Text.RegularExpressions;
public void DeleteAll()
{
ObjectContext objectContext = ( (IObjectContextAdapter)context ).ObjectContext;
string sql = objectContext.CreateObjectSet<T>().ToTraceString();
Regex regex = new Regex( "FROM (?<table>.*) AS" );
Match match = regex.Match( sql );
string tableName = match.Groups[ "table" ].Value;
context.Database.ExecuteSqlCommand( string.Format( "delete from {0}", tableName ) );
}
First block of code retrievs the table name needed in ExecuteSqlCommand method.
Usage:
using ( var context = new UnitOfWork() )
{
context.MyRepository.DeleteAll();
}