2016-05-10 2 views
0

Ich arbeite verwalteten gespeicherten Prozeduren auf die Reduzierung und haben über diese kommen nicht zu wissen, wie (oder ob) es erfolgreich auf Entity Framework portiert werden:Wie wird eine Spalte des gelöschten Datensatzes zurückgegeben, wenn ein Datensatz in EF gelöscht wird?

-- select out filename so the caller can delete the file from the filesystem 
SELECT SystemFileName 
FROM File 
WHERE FileId = @fileId 

-- now delete 
DELETE 
FROM File 
WHERE FileId = @fileId 

Grundsätzlich nimmt die proc eine ID, die Datei zurückgibt Name des zu löschenden Datensatzes und löscht die Zeile. Der aufrufende Code hat dann den Dateinamen, um jedes Dateisystem aufzuräumen und das Potential für verwaiste Dateien zu reduzieren.

Jetzt mit Entity Framwork, konnte ich nur alle Dateien finden und die Löschung durchführen, aber wenn ich dies in einer Schleife tun würde, wäre es schrecklich ineffizient.

Ich könnte versuchen, meine Versuche zu dokumentieren, aber es ist mehr Pseudocode als alles, was kompiliert wird.

+0

Sie wollen auch die Ausführung von Raw SQL-Befehle zu vermeiden, wie ich es verstehe? – Evk

+0

Wählen Sie alle Dateiobjekte aus EF DbSet aus, die Sie löschen und in einer Liste speichern möchten. Schleife durch die Liste und entferne jede einzelne oder ich denke, es gibt eine 'RemoveRange' Methode. SaveChanges auf Ihrem DbContext und dann können Sie Ihre Liste durchlaufen und löschen Sie die Dateien – Nkosi

+0

@Evk wahrscheinlich, wenn ich nicht eine vernünftige Alternative zu der Proc sehen könnte, kann ich genauso gut die proc. –

Antwort

1
// Select all the File objects from EF DbSet<File> that you want to delete and store in a List<File>. 
var toDelete = context.Files.Where(predicate).ToList(); 
//loop through the list and remove each one or i think there is a RemoveRange method. 
var deleted = context.Files.RemoveRage(toDelete); 
//SaveChanges on your DbContext 
if(context.SaveChanges() == toDelete.Count) { 
    //and then you can loop through your List and delete the files from system 
    deleted.ToList().ForEach(file => { 
     var fileInfo = new FileInfo(file.SystemFileName); 
     if(fileInfo.Exists) { 
      fileInfo.Delete(); 
     } 
    }); 
} 
+0

Wenn jede Dateizeile viele Spalten enthält, würde das bedeuten, dass die gesamte Zeile zurückgegeben wird, um als Prädikat an RemoveRange übergeben zu werden? –

+0

Ja, das würde bedeuten, dass die ganze Zeile zurückgegeben wird, um als Argumente an 'RemoveRange' übergeben zu werden. In EF entfernen Sie das gesamte Objekt, so dass es irgendwann die Entität abrufen wird. – Nkosi

+0

Also ich habe diesen Ansatz genommen, ich bin nicht ganz glücklich, dass Sie die ganze Reihe benötigen, aber ich nehme die Einfachheit davon. –

1

Unter der Annahme, dass Sie weniger als 4000 Datensätze zu löschen, warum nicht

1) Wählen Sie die ID und Dateiname Sie 2) Bewahren Sie diese Ergebnisse in einem Array/Liste 3) Löschen Sie alle Datensätze löschen möchten, mit die Klausel IN

// get all of the records to be deleted 
var records = context.Files.Where(x => x.Name.Contains("delete-me")).Select(x => new {x.Id, x.Name}).ToList(); 

// mark all of our files to be deleted 
context.Files.RemoveAll(x => records.Contains(x.Id)); // not sure if this line is correct as I am writing this in notepad, but it will give you a good enough idea 

// execute our save, which will delete our records 
context.Save(); 

// return the list of records that have been deleted back to the caller 
return records; 
+0

Ist 4000 ein (vernünftiger?) Willkürlicher Betrag oder gibt es einen technischen Grund, würde ich eine andere Methode in Erwägung ziehen, wenn es mehr Datensätze gäbe? –

+0

Phil, 4000 ist die maximale Anzahl von Operatoren, die eine IN-Anweisung in SQL Server verarbeiten kann. Wenn Sie mehr als 4000 tun, dann müssen Sie eine Art von Batch-Mechanismus haben – Kane

+0

Danke für die Klarstellung, wenn nicht nur für mich, sondern für alle anderen, die darüber stolpert. –

0

Um ehrlich zu sein, ich würde das ein Massenbetrieb und nicht ein großer Kandidat für EF (oder andere ORMs für diese Angelegenheit) in Betracht ziehen. Ich bin mir nicht sicher, was für Sie wichtiger ist, die Abfrage vereinfachen oder EF verwenden. Aber wenn Sie die Abfrage vereinfachen möchten, können Sie so etwas ausführen und die betroffenen gelöschten Werte gleichzeitig lesen

DELETE 
OUTPUT deleted.SystemFileName -- or OUTPUT deleted.* 
FROM File 
WHERE FileId = @fileId