J'essaie de supprimer plusieurs lignes d'une table.
Dans SQL Server normal, cela serait simple comme ceci:
DELETE FROM Table
WHERE
Table.Column = 'SomeRandomValue'
AND Table.Column2 = 'AnotherRandomValue'
Dans Entity Framework 6, ils ont introduit la méthode RemoveRange () .
Cependant, lorsque je l'utilise, plutôt que de supprimer des lignes à l'aide des clauses where que j'ai fournies, Entity Framework interroge la base de données pour obtenir toutes les lignes correspondant aux clauses where et les supprimer une à une à l'aide de leurs clés primaires.
Est-ce la limitation actuelle d'EntityFramework? Ou est-ce que j'utilise RemoveRange()
de manière erronée?
Voici comment j'utilise RemoveRange()
:
db.Tables.RemoveRange(
db.Tables
.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomValue')
);
Je pense que nous avons atteint ici une limitation de EF . Parfois, vous devez simplement utiliser ExecuteSqlCommand pour rester performant.
Ce que vous recherchez est une bibliothèque de suppression par lots qui supprime plusieurs enregistrements d'une base de données d'une requête LINQ sans charger d'entités.
Plusieurs bibliothèques prenant en charge cette fonctionnalité existent.
Vous pouvez trouver la liste ici: Bibliothèque de suppression de lot d'Entity Framework
Disclaimer: Je suis propriétaire du projet Entity Framework Plus
// using Z.EntityFramework.Plus; // Don't forget to include this.
// DELETE directly in SQL (without loading entities)
db.Tables.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomValue')
.Delete();
// DELETE using a BatchSize
db.Tables.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomValue')
.Delete(x => x.BatchSize = 1000);
Wiki: EF + Suppression de lot
var db1 = db.Tables
.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList();
db.Tables.RemoveRange(db1);
db.SaveChanges();
Utilisez une liste Variable to Store Removable et transmettez-la à RemoveRange ().
Je fais habituellement comme ça, et c’est le travail . Hope Cela fonctionne aussi dans votre cas.
C'est un peu cassé, essayez
db.Tables.RemoveRange(
db.Tables
.Where(_ => _.Column == 'SomeRandomValue'
&& _.Column2 == 'AnotherRandomeValue').AsEnumerable().ToList()
);
db.SaveChanges();
Je m'occupe de cela moi-même et je suis d'accord avec Adi - utilisez simplement SQL.
Je nettoie les anciennes lignes d'une table de journal et EF RemoveRange a pris 3 minutes pour faire la même chose que cela a fait en 3 secondes:
DELETE FROM LogEntries WHERE DATEDIFF(day, GETDATE(), Date) < -6
Date est le nom de la colonne contenant la date. Pour le rendre correct, utilisez un paramètre, bien sûr, comme ceci:
context.Database.ExecuteSqlCommand
("DELETE FROM LogEntries WHERE DATEDIFF(day, GETDATE(), Date) < @DaysOld", new System.Data.SqlClient.SqlParameter(
"DaysOld", - Settings.DaysToKeepDBLogEntries));
Notez qu'il y a beaucoup de lignes impliquées dans mon cas. Lorsque j'ai démarré le projet et que je n'avais pas beaucoup de données, RemoveRange fonctionnait bien.
Reculez et réfléchissez. Voulez-vous vraiment télécharger les enregistrements de la base de données afin de les supprimer? Ce n'est pas parce que vous pouvez en faire une bonne idée.
Peut-être pourriez-vous envisager de supprimer les éléments de la base de données avec une procédure stockée? EF permet aussi de faire ça ...
Pourquoi n'avez-vous pas simplement un adaptateur dans la base de données et envoyez-vous simplement la commande de suppression appropriée, comme dans votre exemple?