Wie lösche ich mehrere Zeilen in Entity Framework (ohne foreach)

305

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?

Jon Galloway
quelle
1
Möglicherweise möchten Sie die akzeptierte Antwort erneut aufrufen.
Eric J.
1
Wenn Sie performant bleiben möchten, möchten Sie vielleicht meine Antwort hier überprüfen stackoverflow.com/a/35033286/274589
Adi

Antworten:

49

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.

Alex James
quelle
ExecuteStoreCommand ist kein richtiger Weg. DeleteAllSubmit arbeitet in Linq to SQL, aber nicht im Entity Framework. Ich möchte die gleiche Option im Entity Framework.
Hiral
653

EntityFramework 6 hat dies mit etwas einfacher gemacht .RemoveRange().

Beispiel:

db.People.RemoveRange(db.People.Where(x => x.State == "CA"));
db.SaveChanges();
Kyle
quelle
31
Genau das brauchen wir ... Außer wenn ich es in einem ausreichend großen Bereich verwende, kommt es zu einer Ausnahme wegen Speichermangel! Ich dachte, der springende Punkt bei RemoveRange wäre, die Verarbeitung an die Datenbank zu übergeben, aber anscheinend nicht.
Samer Adra
Dies ist WAAAYYYY schneller als das Setzen des Status "Gelöscht" für jede Entität!
Jerther
54
Sicher ist diese Antwort einfacher, aber in Bezug auf die Leistung ist sie möglicherweise nicht großartig. Warum? Was genau dieses Doet ist, ist wie das Löschen in jeder for-Schleife, es ruft zuerst alle Zeilen ab und löscht dann eins nach dem anderen. Nur der Gewinn dient zum Speichern von "DetectChanges wird einmal aufgerufen, bevor Entitäten gelöscht werden, und wird nicht erneut aufgerufen" Versuchen Sie es mit dem Tool, um zu sehen, wie SQL generiert wird.
Anshul Nigam
6
Versuchen Sie für einen ausreichend großen Bereich etwas wie .Take (10000) und eine Schleife bis RemoveRange (...). Count () == 0.
Eric J.
20
Das Problem besteht darin, dass der Eingabeparameter RemoveRange ein IEnumerable ist. Um einen Löschvorgang durchzuführen, werden alle Entitäten aufgelistet und 1 DELETE-Abfrage pro Entität ausgeführt.
Bubi
74

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?

Nun ja, außer Sie können es zu einem Zweiliner machen:

context.Widgets.Where(w => w.WidgetId == widgetId)
               .ToList().ForEach(context.Widgets.DeleteObject);
context.SaveChanges();
Klaus Byskov Pedersen
quelle
76
Sie machen eine ToList (), die den Zweck zunichte macht. Wie unterscheidet sich das von der ursprünglichen Lösung?
Lahsrah
3
Ich habe Probleme, da ich nur die Remove-Methode im Kontextobjekt habe.
Pnct
2
Dies ist definitiv keine geeignete Lösung, wenn eine Million Zeilen (oder sogar einige hundert) erwartet werden. Wenn wir jedoch sicher sind, dass es nur wenige Zeilen geben wird, ist diese Lösung ordentlich und funktioniert einwandfrei. Ja, es würde ein paar Roundtrips zur DB beinhalten, aber meiner Meinung nach überwiegt die verlorene Abstraktion beim direkten Aufruf von SQL die Vorteile.
Yogster
Entity Framework funktioniert, wie der Name schon sagt, am besten mit Daten auf Entitätsebene. Massendatenoperationen werden am besten von guten alten gespeicherten Prozessen verarbeitet. In Bezug auf die Leistung sind sie bei weitem die besten Optionen und schlagen jede EF-Logik, die eine Schleife erfordert.
Paceman
72
using (var context = new DatabaseEntities())
{
    context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
}
Vlad Bezden
quelle
Aber wie kann man das mit einer Liste von IDs machen? Diese Lösung verarbeitet "Listen" nicht sehr gut.
JesseNewman19
11
@ JesseNewman19 Wenn Sie bereits eine Liste von IDs haben, verwenden Sie a WHERE IN ({0}), und dann sollte das zweite Argument sein String.Join(",", idList).
Langdon
@Langdon, das wird nicht funktionieren, weil es den Befehl wie folgt an SQL sendet: WHERE IN ("1, 2, 3"). Die Datenbank gibt dann einen Fehler aus, weil Sie eine Zeichenfolge anstelle einer Liste von Ganzzahlen übergeben haben.
JesseNewman19
Ich möchte mit LINQ eine solche Aussage generieren. Das nächste, was ich fand, war eine Bibliothek. EntityFramework.Extended
Jaider
Wenn Sie verwenden String.Join, müssen Sie möglicherweise string.Formatdie 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?
Andrew
50

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:

public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
    string selectSql = db.Set<T>().Where(filter).ToString();
    string fromWhere = selectSql.Substring(selectSql.IndexOf("FROM"));
    string deleteSql = "DELETE [Extent1] " + fromWhere;
    db.Database.ExecuteSqlCommand(deleteSql);
}

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 :

public static void DeleteWhere<T>(this DbContext db, Expression<Func<T, bool>> filter) where T : class
{
    var query = db.Set<T>().Where(filter);

    string selectSql = query.ToString();
    string deleteSql = "DELETE [Extent1] " + selectSql.Substring(selectSql.IndexOf("FROM"));

    var internalQuery = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_internalQuery").Select(field => field.GetValue(query)).First();
    var objectQuery = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(field => field.Name == "_objectQuery").Select(field => field.GetValue(internalQuery)).First() as ObjectQuery;
    var parameters = objectQuery.Parameters.Select(p => new SqlParameter(p.Name, p.Value)).ToArray();

    db.Database.ExecuteSqlCommand(deleteSql, parameters);
}

Es erfordert ein wenig Nachdenken, funktioniert aber gut.

Thanh Nguyen
quelle
Was ist DbContext? Ich nehme Ihren automatisch generierten Entity Framework-Kontext an. Ich habe keine Methode namens Set <T>.
Stealth Rabbi
@Stealth: Ja, es ist Ihr EF-Datenkontext. Ich verwende zuerst Code, aber der automatisch generierte Kontext sollte der gleiche sein. Entschuldigung für die falsch eingegebene Anweisung: Set <T> () (meine Firma beschränkt den Internetzugang, ich konnte den Code nicht einfügen, musste ihn von Hand eingeben, also ...), Codes aktualisiert :)
Thanh Nguyen
3
Dies ist die einzige Antwort, die die Frage tatsächlich beantwortet! Jede andere Antwort löscht jedes einzelne Element einzeln, unglaublich.
Rocklan
Dies scheint die richtigste Antwort zu sein. Es ermöglicht das Löschen auf sehr allgemeine Weise und verlagert die Arbeit ordnungsgemäß in die Datenbank und nicht in das C #.
JesseNewman19
1
Für all die weniger technischen Programmierer da draußen wollte ich etwas genauer erläutern, wie diese hervorragende und generische Lösung implementiert werden kann, da ich dadurch ein paar Minuten Zeit gespart hätte! Fortsetzung im nächsten Kommentar ...
jdnew18
30

Für alle Benutzer von EF5 kann die folgende Erweiterungsbibliothek verwendet werden: https://github.com/loresoft/EntityFramework.Extended

context.Widgets.Delete(w => w.WidgetId == widgetId);
Marcelo Mason
quelle
3
Hat Leistungsprobleme bei großen Tischen, die in meiner Situation nicht verwendet werden können.
Tomas
@Tomas Welche Art von Leistung haben Sie bemerkt? Wie schwerwiegend war das Problem und wie groß war der Tisch? Kann das noch jemand bestätigen?
Anestis Kivranoglou
Es ist wirklich schnell im Vergleich zu den Alternativen da draußen
Jaider
Ich kann Delete()in EF6 keine Funktion in meinen Entitäten sehen.
dotNET
context.Widgets.Where(w => w.WidgetId == widgetId).Delete();ist der neuere Weg mit EntityFramework.Extended
Peter Kerr
11

Es 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:

var ids = from w in context.Widgets where w.WidgetId == widgetId select w.Id;
context.Widgets.RemoveRange(from id in ids.AsEnumerable() select new Widget { Id = id });
Edward Brey
quelle
Seien Sie vorsichtig - dies kann die Entitätsüberprüfung von Entity Framework fehlschlagen, da Ihre Stub- WidgetObjekte nur eine initialisierte IdEigenschaft haben. Der Weg dahin ist zu verwenden context.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.
Sammy S.
@SammyS. Ich habe das noch nicht erlebt, kann also nicht mit den Details sprechen, aber es scheint seltsam, dass EF sich um die Validierung kümmert, wenn es die Zeile trotzdem löscht.
Edward Brey
Du bist absolut richtig. Ich habe das deletemit einer ähnlichen Problemumgehung für updateEntitäten verwechselt , ohne sie zu laden.
Sammy S.
10

EF 6.1

public void DeleteWhere<TEntity>(Expression<Func<TEntity, bool>> predicate = null) 
where TEntity : class
{
    var dbSet = context.Set<TEntity>();
    if (predicate != null)
        dbSet.RemoveRange(dbSet.Where(predicate));
    else
        dbSet.RemoveRange(dbSet);

    context.SaveChanges();
} 

Verwendungszweck:

// Delete where condition is met.
DeleteWhere<MyEntity>(d => d.Name == "Something");

Or:

// delete all from entity
DeleteWhere<MyEntity>();
mnsr
quelle
7
Dies ist effektiv dasselbe wie db.People.RemoveRange (db.People.Where (x => x.State == "CA")); db.SaveChanges (); Also kein Leistungsgewinn.
ReinierDG
4

Für EF 4.1

var objectContext = (myEntities as IObjectContextAdapter).ObjectContext;
objectContext.ExecuteStoreCommand("delete from [myTable];");
Amit Pawar
quelle
1
Dies funktioniert, aber der springende Punkt bei der Verwendung von Entity Framework ist die objektorientierte Interaktion mit der Datenbank. Hiermit wird nur die SQL-Abfrage direkt ausgeführt.
Arturo Torres Sánchez
4

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.

UUHHIVS
quelle
Zahlen Sie 600 $ + für den Bulk-SQL-Betriebsgenerator. Ernsthaft?
nicolay.anykienko
@ nicolay.anykienko Als ich es benutzte, war diese Bibliothek kostenlos, es gibt andere Operationen, bei denen Sie bezahlen müssen, richtig nicht, ich weiß nicht, ob Sie bezahlen müssen
UUHHIVS
3

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.

CREATE TABLE [act].[Lists]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
    [Name] NVARCHAR(50) NOT NULL
)
GO
CREATE UNIQUE INDEX [IU_Name] ON [act].[Lists] ([Name])
GO
CREATE TABLE [act].[ListItems]
(
    [Id] INT NOT NULL IDENTITY, 
    [ListId] INT NOT NULL, 
    [Item] NVARCHAR(100) NOT NULL, 
    CONSTRAINT PK_ListItems_Id PRIMARY KEY NONCLUSTERED (Id),
    CONSTRAINT [FK_ListItems_Lists] FOREIGN KEY ([ListId]) REFERENCES [act].[Lists]([Id]) ON DELETE CASCADE
)
go
CREATE UNIQUE CLUSTERED INDEX IX_ListItems_Item 
ON [act].[ListItems] ([ListId], [Item]); 
GO

CREATE PROCEDURE [act].[DeleteAllItemsInList]
    @listId int
AS
    DELETE FROM act.ListItems where ListId = @listId
RETURN 0

Nun der interessante Teil des Löschens der Elemente und des Aktualisierens des Entity-Frameworks mithilfe einer Erweiterung.

public static class ListExtension
{
    public static void DeleteAllListItems(this List list, ActDbContext db)
    {
        if (list.Id > 0)
        {
            var listIdParameter = new SqlParameter("ListId", list.Id);
            db.Database.ExecuteSqlCommand("[act].[DeleteAllItemsInList] @ListId", listIdParameter);
        }
        foreach (var listItem in list.ListItems.ToList())
        {
            db.Entry(listItem).State = EntityState.Detached;
        }
    }
}

Der Hauptcode kann es jetzt wie folgt verwenden

[TestMethod]
public void DeleteAllItemsInListAfterSavingToDatabase()
{
    using (var db = new ActDbContext())
    {
        var listName = "TestList";
        // Clean up
        var listInDb = db.Lists.Where(r => r.Name == listName).FirstOrDefault();
        if (listInDb != null)
        {
            db.Lists.Remove(listInDb);
            db.SaveChanges();
        }

        // Test
        var list = new List() { Name = listName };
        list.ListItems.Add(new ListItem() { Item = "Item 1" });
        list.ListItems.Add(new ListItem() { Item = "Item 2" });
        db.Lists.Add(list);
        db.SaveChanges();
        listInDb = db.Lists.Find(list.Id);
        Assert.AreEqual(2, list.ListItems.Count);
        list.DeleteAllListItems(db);
        db.SaveChanges();
        listInDb = db.Lists.Find(list.Id);
        Assert.AreEqual(0, list.ListItems.Count);
    }
}
Xavier John
quelle
Vielen Dank für ein schönes Beispiel für die Verwendung einer gespeicherten Prozedur und deren anschließende Implementierung als Erweiterung mit dem Verwendungscode.
Glenn Garson
3

Wenn Sie alle Zeilen einer Tabelle löschen möchten, können Sie den Befehl sql ausführen

using (var context = new DataDb())
{
     context.Database.ExecuteSqlCommand("TRUNCATE TABLE [TableName]");
}

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.

Amir
quelle
3
Sie sollten auch erwähnen, dass Sie nicht truncate tablefü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-Dokumentation
Breitband
2

UUHHIVS's ist eine sehr elegante und schnelle Methode zum Löschen von Stapeln, die jedoch mit Vorsicht verwendet werden muss:

  • Automatische Generierung von Transaktionen: Die Abfragen werden von einer Transaktion erfasst
  • Unabhängigkeit des Datenbankkontexts: Die Ausführung hat nichts damit zu tun 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:

var repo = DataAccess.EntityRepository;
var existingData = repo.All.Where(x => x.ParentId == parentId);  

TransactionScope scope = null;
try
{
    // this starts the outer transaction 
    using (scope = new TransactionScope(TransactionScopeOption.Required))
    {
        // this starts and commits an inner transaction
        existingData.Delete();

        // var toInsert = ... 

        // this relies on EntityFramework.BulkInsert library
        repo.BulkInsert(toInsert);

        // any other context changes can be performed

        // this starts and commit an inner transaction
        DataAccess.SaveChanges();

        // this commit the outer transaction
        scope.Complete();
    }
}
catch (Exception exc)
{
    // this also rollbacks any pending transactions
    scope?.Dispose();
}
Alexei
quelle
2

Entity Framework Core

3,1 3,0 2,2 2,1 2,0 1,1 1,0

using (YourContext context = new YourContext ())
{
    var widgets = context.Widgets.Where(w => w.WidgetId == widgetId);
    context.Widgets.RemoveRange(widgets);
    context.SaveChanges();
}

Zusammenfassung :

Entfernt die angegebene Sammlung von Entitäten aus dem Kontext, der der Gruppe zugrunde liegt, wobei jede Entität in den Status "Gelöscht" versetzt wird, sodass sie beim Aufruf von SaveChanges aus der Datenbank gelöscht wird.

Anmerkungen :

Beachten Sie, dass DetectChanges vor dem Löschen von Entitäten einmal aufgerufen und nicht erneut aufgerufen wird, wenn System.Data.Entity.Infrastructure.DbContextConfiguration.AutoDetectChangesEnabled auf true gesetzt ist (dies ist die Standardeinstellung). Dies bedeutet, dass RemoveRange in einigen Situationen möglicherweise eine deutlich bessere Leistung erbringt als ein mehrmaliger Aufruf von Remove. Beachten Sie, dass, wenn im Kontext Hinzugefügt eine Entität im Kontext vorhanden ist, diese Methode dazu führt, dass sie vom Kontext getrennt wird. Dies liegt daran, dass davon ausgegangen wird, dass eine hinzugefügte Entität nicht in der Datenbank vorhanden ist, sodass der Versuch, sie zu löschen, keinen Sinn ergibt.

Nguyen Van Thanh
quelle
1

Sie können SQL-Abfragen wie folgt direkt ausführen:

    private int DeleteData()
{
    using (var ctx = new MyEntities(this.ConnectionString))
    {
        if (ctx != null)
        {

            //Delete command
            return ctx.ExecuteStoreCommand("DELETE FROM ALARM WHERE AlarmID > 100");

        }
    }
    return 0;
}

Für die Auswahl können wir verwenden

using (var context = new MyContext()) 
{ 
    var blogs = context.MyTable.SqlQuery("SELECT * FROM dbo.MyTable").ToList(); 
}
Abhishek Sharma
quelle
Da EF die Zuordnung von Löschbedingungen nicht ordnungsgemäß unterstützt, ist dies wahrscheinlich die beste Wahl, um die Aufgabe zu erledigen.
Tony O'Hagan
1

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:

List<Widgets> widgetList = context.Widgets
              .Where(w => w.WidgetId == widgetId).ToList<Widgets>();

context.Widgets.DeleteAllOnSubmit(widgetList);

context.SubmitChanges();

Wahrscheinlich wird intern immer noch eine Schleife verwendet.

Hugo Nava Kopp
quelle
3
Sieht so aus, als ob Sie falsch verstehen, was ein varist.
Freiheit-m
1

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.

// make a list of items to delete or just use conditionals against fields
var idsToFilter = dbContext.Products
    .Where(p => p.IsExpired)
    .Select(p => p.ProductId)
    .ToList();

// build the expression
Expression<Func<Product, bool>> deleteList = 
    (a) => idsToFilter.Contains(a.ProductId);

// Run the extension method (make sure you have `using namespace` at the top)
dbContext.RemoveWhere(deleteList);

Dies erzeugte eine einzelne Löschanweisung für die Gruppe.

Steve Greene
quelle
0

EF 6. =>

var assignmentAddedContent = dbHazirBot.tbl_AssignmentAddedContent.Where(a =>
a.HazirBot_CategoryAssignmentID == categoryAssignment.HazirBot_CategoryAssignmentID);
dbHazirBot.tbl_AssignmentAddedContent.RemoveRange(assignmentAddedContent);
dbHazirBot.SaveChanges();
Erçin Dedeoğlu
quelle
0

Beste : in EF6 => .RemoveRange()

Beispiel:

db.Table.RemoveRange(db.Table.Where(x => Field == "Something"));
maXXis
quelle
14
Wie unterscheidet sich das von Kyles Antwort?
-1

Siehe die Antwort "Lieblingscode", die funktioniert

So habe ich es benutzt:

     // Delete all rows from the WebLog table via the EF database context object
    // using a where clause that returns an IEnumerable typed list WebLog class 
    public IEnumerable<WebLog> DeleteAllWebLogEntries()
    {
        IEnumerable<WebLog> myEntities = context.WebLog.Where(e => e.WebLog_ID > 0);
        context.WebLog.RemoveRange(myEntities);
        context.SaveChanges();

        return myEntities;
    }
Brian Quinn
quelle
1
Wie unterscheidet sich Ihre Antwort von der Antwort von user1308743 ?
Sergey Berezovskiy
Ich habe einfach ein Arbeitsbeispiel geteilt. Was auch immer ich tun kann, um für die Hilfe, die ich hier bekomme, etwas zurückzugeben.
Brian Quinn
-3

In EF 6.2 funktioniert dies einwandfrei, indem der Löschvorgang direkt an die Datenbank gesendet wird, ohne zuvor die Entitäten zu laden:

context.Widgets.Where(predicate).Delete();

Mit einem festen Prädikat ist es ganz einfach:

context.Widgets.Where(w => w.WidgetId == widgetId).Delete();

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:

Expression<Func<Widget, bool>> predicate = PredicateBuilder.New<Widget>(x => x.UserID == userID);
if (somePropertyValue != null)
{
    predicate = predicate.And(w => w.SomeProperty == somePropertyValue);
}
context.Widgets.Where(predicate).Delete();
Vladimir
quelle
1
Mit Raw EF 6.2 ist dies nicht möglich. Vielleicht benutzt du Z.EntityFramework.Plusoder ähnliches? ( entityframework.net/batch-delete )
Sammy S.
Das erste ist Raw EF 6.2 und funktioniert zu finden. Der zweite ist, wie bereits erwähnt, die Verwendung von LINQKit.
Vladimir
1
Hmm, ich kann diese Methode nicht finden. Können Sie überprüfen, in welcher Klasse und in welchem ​​Namespace sich diese Methode befindet?
Sammy S.
Ich drittens ( Delete()Methode ist von Natur aus nicht vorhanden).
Summe keine