Ich lösche mehrere Elemente mit Entity Framework aus einer Tabelle. Es gibt keinen Fremdschlüssel / übergeordnetes Objekt, daher kann ich dies mit OnDeleteCascade nicht verarbeiten.
Im Moment mache ich das:
var widgets = context.Widgets
.Where(w => w.WidgetId == widgetId);
foreach (Widget widget in widgets)
{
context.Widgets.DeleteObject(widget);
}
context.SaveChanges();
Es funktioniert, aber der Foreach nervt mich. Ich verwende EF4, möchte aber kein SQL ausführen. Ich möchte nur sicherstellen, dass mir nichts entgeht - das ist so gut wie es nur geht, oder? Ich kann es mit einer Erweiterungsmethode oder einem Helfer abstrahieren, aber irgendwo machen wir immer noch einen Foreach, oder?
entity-framework
Jon Galloway
quelle
quelle
Antworten:
Wenn Sie SQL nicht direkt ausführen möchten, ist das Aufrufen von DeleteObject in einer Schleife das Beste, was Sie heute tun können.
Sie können SQL jedoch ausführen und es dennoch über eine Erweiterungsmethode ganz allgemein verwenden, indem Sie den hier beschriebenen Ansatz verwenden .
Obwohl diese Antwort für 3.5 war. Für 4.0 würde ich wahrscheinlich die neue ExecuteStoreCommand-API unter der Haube verwenden, anstatt auf StoreConnection zuzugreifen.
quelle
EntityFramework 6 hat dies mit etwas einfacher gemacht
.RemoveRange()
.Beispiel:
quelle
Nun ja, außer Sie können es zu einem Zweiliner machen:
quelle
quelle
WHERE IN ({0})
, und dann sollte das zweite Argument seinString.Join(",", idList)
.EntityFramework.Extended
String.Join
, müssen Sie möglicherweisestring.Format
die bereits gebildete SQL-Zeichenfolge verwenden und an den Befehl übergeben. Solange Ihre Liste nur Ganzzahlen enthält, besteht kein Risiko eines Injektionsangriffs. Überprüfen Sie diese Frage: Wie kann ich ein Array an einen Befehl zum Ausführen eines Speichers übergeben?Ich weiß, dass es ziemlich spät ist, aber falls jemand eine einfache Lösung benötigt, ist das Coole, dass Sie auch die where-Klausel hinzufügen können:
Hinweis: gerade mit MSSQL2008 getestet.
Aktualisieren:
Die obige Lösung funktioniert nicht, wenn EF eine SQL-Anweisung mit Parametern generiert. Hier ist das Update für EF5 :
Es erfordert ein wenig Nachdenken, funktioniert aber gut.
quelle
Für alle Benutzer von EF5 kann die folgende Erweiterungsbibliothek verwendet werden: https://github.com/loresoft/EntityFramework.Extended
quelle
Delete()
in EF6 keine Funktion in meinen Entitäten sehen.context.Widgets.Where(w => w.WidgetId == widgetId).Delete();
ist der neuere Weg mit EntityFramework.ExtendedEs scheint immer noch verrückt zu sein, etwas vom Server zurückziehen zu müssen, um es zu löschen, aber zumindest die IDs zurückzubekommen, ist viel schlanker als das Abrufen der vollständigen Entitäten:
quelle
Widget
Objekte nur eine initialisierteId
Eigenschaft haben. Der Weg dahin ist zu verwendencontext.Configuration.ValidateOnSaveEnabled = false
(zumindest in EF6). Dies deaktiviert die eigene Validierung von Entity Framework, führt aber natürlich weiterhin die eigene Validierung der Datenbank durch.delete
mit einer ähnlichen Problemumgehung fürupdate
Entitäten verwechselt , ohne sie zu laden.EF 6.1
Verwendungszweck:
quelle
Für EF 4.1
quelle
Sie können dafür Erweiterungsbibliotheken wie EntityFramework.Extended oder Z.EntityFramework.Plus.EF6 verwenden, die für EF 5, 6 oder Core verfügbar sind. Diese Bibliotheken bieten eine hervorragende Leistung, wenn Sie sie löschen oder aktualisieren müssen, und sie verwenden LINQ. Beispiel zum Löschen ( Quelle plus ):
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2)) .Delete();
oder ( Quelle erweitert )
context.Users.Where(u => u.FirstName == "firstname") .Delete();
Diese verwenden native SQL-Anweisungen, sodass die Leistung großartig ist.
quelle
Der schnellste Weg zum Löschen ist die Verwendung einer gespeicherten Prozedur. Ich bevorzuge gespeicherte Prozeduren in einem Datenbankprojekt gegenüber dynamischem SQL, da Umbenennungen korrekt behandelt werden und Compilerfehler auftreten. Dynamic SQL kann auf Tabellen verweisen, die gelöscht / umbenannt wurden und Laufzeitfehler verursachen.
In diesem Beispiel habe ich zwei Tabellen List und ListItems. Ich brauche einen schnellen Weg, um alle ListItems einer bestimmten Liste zu löschen.
Nun der interessante Teil des Löschens der Elemente und des Aktualisierens des Entity-Frameworks mithilfe einer Erweiterung.
Der Hauptcode kann es jetzt wie folgt verwenden
quelle
Wenn Sie alle Zeilen einer Tabelle löschen möchten, können Sie den Befehl sql ausführen
TRUNCATE TABLE (Transact-SQL) Entfernt alle Zeilen aus einer Tabelle, ohne die einzelnen Zeilenlöschungen zu protokollieren. TRUNCATE TABLE ähnelt der DELETE-Anweisung ohne WHERE-Klausel. TRUNCATE TABLE ist jedoch schneller und benötigt weniger System- und Transaktionsprotokollressourcen.
quelle
truncate table
für Tabellen ausgeführt werden können, auf die durch eine FOREIGN KEY-Einschränkung verwiesen wird. (Sie können eine Tabelle mit einem Fremdschlüssel abschneiden, der auf sich selbst verweist.) MSDN-DokumentationUUHHIVS
's ist eine sehr elegante und schnelle Methode zum Löschen von Stapeln, die jedoch mit Vorsicht verwendet werden muss:context.SaveChanges()
Diese Probleme können umgangen werden, indem die Kontrolle über die Transaktion übernommen wird. Der folgende Code veranschaulicht das Batch-Löschen und Masseneinfügen auf transaktionale Weise:
quelle
Entity Framework Core
Zusammenfassung :
Anmerkungen :
quelle
Sie können SQL-Abfragen wie folgt direkt ausführen:
Für die Auswahl können wir verwenden
quelle
Sie können auch die DeleteAllOnSubmit () -Methode verwenden, indem Sie Ihre Ergebnisse in einer generischen Liste anstatt in var übergeben. Auf diese Weise reduziert sich Ihr foreach auf eine Codezeile:
Wahrscheinlich wird intern immer noch eine Schleife verwendet.
quelle
var
ist.Thanhs Antwort funktionierte am besten für mich. Alle meine Datensätze in einer einzigen Serverreise gelöscht. Ich hatte Probleme damit, die Erweiterungsmethode tatsächlich aufzurufen, und dachte, ich würde meine teilen (EF 6):
Ich habe die Erweiterungsmethode einer Hilfsklasse in meinem MVC-Projekt hinzugefügt und den Namen in "RemoveWhere" geändert. Ich füge einen dbContext in meine Controller ein, aber Sie können auch einen ausführen
using
.Dies erzeugte eine einzelne Löschanweisung für die Gruppe.
quelle
EF 6. =>
quelle
Beste :
in EF6 => .RemoveRange()
Beispiel:
quelle
Siehe die Antwort "Lieblingscode", die funktioniert
So habe ich es benutzt:
quelle
In EF 6.2 funktioniert dies einwandfrei, indem der Löschvorgang direkt an die Datenbank gesendet wird, ohne zuvor die Entitäten zu laden:
Mit einem festen Prädikat ist es ganz einfach:
Und wenn Sie ein dynamisches Prädikat benötigen, schauen Sie sich LINQKit (Nuget-Paket verfügbar) an. In meinem Fall funktioniert so etwas gut:
quelle
Z.EntityFramework.Plus
oder ähnliches? ( entityframework.net/batch-delete )Delete()
Methode ist von Natur aus nicht vorhanden).