Quel est le meilleur moyen de supprimer tous les éléments d'un System.Data.Entity.DbSet, avec Entity Framework 4.3?
dbContext.Database.ExecuteSqlCommand("delete from MyTable");
(Sans blague.)
Le problème est qu’EF ne prend en charge aucune commande par lot et que le seul moyen de supprimer toutes les entités d’un ensemble sans DML direct serait:
foreach (var entity in dbContext.MyEntities)
dbContext.MyEntities.Remove(entity);
dbContext.SaveChanges();
Ou peut-être un peu moins cher pour éviter de charger des entités complètes:
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();
Mais dans les deux cas, vous devez charger all entités ou all propriétés de clé et supprimer les entités une par une de l'ensemble. De plus, lorsque vous appelez SaveChanges
, EF enverra à la base de données n (= nombre d'entités de l'ensemble) DELETE qui seront également exécutées une par une dans la base de données (dans une transaction unique).
Donc, le SQL direct est clairement préférable à cette fin, car vous n'avez besoin que d'une seule instruction DELETE.
Voici une autre façon de le faire dans le code.
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;
}
}
}
Pour appeler réellement la méthode et effacer le jeu:
myDbContext.DeleteAll<MyPocoClassName>();
Ancien post, mais il existe maintenant une méthode RemoveRange:
dbContext.MyEntities.RemoveRange(dbContext.MyEntities);
dbContext.SaveChanges();
Si vous souhaitez supprimer tous les éléments sans écrire de code SQL et exécuter uniquement un appel Single Db Call
Bibliothèque étendue Entity Framework propose une méthode batch delete.
context.Users.Delete();
Comme la réponse acceptée ne mentionne que la méthode ci-dessous:
context.Database.ExecuteSqlCommand("delete from MyTable");
et donne plutôt des alternatives à cela, j’ai réussi à écrire une méthode, que vous pouvez utiliser pour éviter de charger toutes les entités, puis les bouclant et utilisant ExecuteSqlCommand à la place.
En supposant que l'on utilise l'unité de travail, où le contexte est 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 ) );
}
Le premier bloc de code récupère le nom de la table nécessaire dans ExecuteSqlCommand method.
using ( var context = new UnitOfWork() )
{
context.MyRepository.DeleteAll();
}
Il n'y a pas besoin d'appeler
context.SaveChanges()
Si vous travaillez avec une unité de travail et un référentiel générique, les éléments suivants peuvent vous être utiles.
public virtual void DeleteWhere(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
foreach (var entity in query)
{
context.Entry(entity).State = EntityState.Deleted;
}
}
Usage:
uow.myRepositoryName.DeleteWhere(u => u.RoomId == roomId);
uow.Save();
Vous pouvez y arriver en utilisant une requête directe:
ent.Database.ExecuteSqlCommand("delete from tablename");