Was ist der beste Weg, um alle Elemente in einem System.Data.Entity.DbSet mit Entity Framework 4.3 zu entfernen?
quelle
Was ist der beste Weg, um alle Elemente in einem System.Data.Entity.DbSet mit Entity Framework 4.3 zu entfernen?
dbContext.Database.ExecuteSqlCommand("delete from MyTable");
(Im Ernst.)
Das Problem ist, dass EF keine Stapelbefehle unterstützt und die einzige Möglichkeit, alle Entitäten in einem Satz ohne direkte DML zu löschen, darin besteht, Folgendes zu tun:
foreach (var entity in dbContext.MyEntities)
dbContext.MyEntities.Remove(entity);
dbContext.SaveChanges();
Oder vielleicht ein bisschen billiger, um das Laden vollständiger Entitäten zu vermeiden:
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();
In beiden Fällen müssen Sie jedoch alle Entitäten oder alle Schlüsseleigenschaften laden und die Entitäten einzeln aus der Gruppe entfernen. Wenn Sie SaveChanges
EF aufrufen, werden außerdem n (= Anzahl der Entitäten in der Menge) DELETE-Anweisungen an die Datenbank gesendet, die auch einzeln in der Datenbank ausgeführt werden (in einer einzelnen Transaktion).
Daher ist Direct SQL für diesen Zweck eindeutig vorzuziehen, da Sie nur eine einzige DELETE-Anweisung benötigen.
SaveChanges
nachdbContext.Database.ExecuteSqlCommand
?RemoveRange
stattRemove
? Würden Sie sagen, "das wurde nur in EF 6 eingeführt und OP nach EF 4 gefragt. *"?Alter Beitrag, aber es gibt jetzt eine RemoveRange-Methode:
quelle
Hier ist eine andere Möglichkeit, wie Sie dies im Code tun können.
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; } } }
So rufen Sie die Methode auf und löschen die Menge:
quelle
Wenn Sie alle Elemente entfernen möchten, ohne SQL zu schreiben, und nur einen einzelnen Datenbankaufruf ausführen möchten
Die erweiterte Entity Framework-Bibliothek bietet eine Batch-Löschmethode .
quelle
In der akzeptierten Antwort wird nur die folgende Methode erwähnt:
context.Database.ExecuteSqlCommand("delete from MyTable");
Ich habe es geschafft, eine Methode zu schreiben, mit der Sie vermeiden können, alle Entitäten zu laden, sie dann zu durchlaufen und stattdessen ExecuteSqlCommand zu verwenden.
Angenommen, Sie verwenden eine Arbeitseinheit, wobei der Kontext DbContext ist:
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 ) ); }
Der erste Codeblock ruft den in der ExecuteSqlCommand- Methode benötigten Tabellennamen ab .
Verwendung:
using ( var context = new UnitOfWork() ) { context.MyRepository.DeleteAll(); }
Sie müssen nicht anrufen
quelle
Wenn Sie mit einer Arbeitseinheit und einem generischen Repository arbeiten, ist Folgendes möglicherweise hilfreich
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; } }
Verwendung:
quelle