Existe-t-il un moyen de supprimer en bloc un ensemble d'objets correspondant à une requête donnée dans LINQ ou LINQ-to-Entities? Les seules références que je peux trouver sont obsolètes, et il semble stupide de parcourir et de supprimer manuellement tous les objets que je souhaite supprimer.Suppression groupée dans LINQ aux entités
Répondre
La question est ancienne (antérieure à EF5). Pour tous ceux qui utilisent EF5, EntityFramework.Extended le fait en un clin d'œil.
Je connais la méthode DeleteAllOnSubmit de tout contexte de données qui va supprimer tous les enregistrements dans la requête. Il doit y avoir une certaine optimisation sous-jacente puisque beaucoup d'objets sont supprimés. Je ne suis pas sûr cependant.
En réalité, aucune optimisation n'est effectuée. Le code SQL généré énumère tous les objets correspondant à votre requête, puis itère manuellement sur ceux-ci pour les supprimer. Certes, l'itération se produit dans la base de données, plutôt que dans votre code, mais vous construisez inutilement un ensemble de résultats simplement pour supprimer son contenu - encore bien pire qu'une simple table "DELETE FROM WHERE foo = bar", qui construit aucun jeu de résultats et couvre la table une seule fois. –
Je ne suis pas sûr de savoir comment il serait efficace, mais vous pouvez essayer quelque chose comme ceci:
// deletes all "People" with the name "Joe"
var mypeople = from p in myDataContext.People
where p.Name == "Joe";
select p;
myDataContext.People.DeleteAllOnSubmit(mypeople);
myDataContext.SubmitChanges();
Cela finit toujours par itérer sur tous les éléments qui correspondent à la requête; il le fait simplement sur la base de données, plutôt que dans votre code. Plus efficace, mais encore loin d'une solution idéale. –
La seule autre façon que je pourrais penser pour le faire, alors, serait de faire myDataContext.ExecuteCommand ("DELETE ...") ;. Loin d'idéal, aussi, mais ça marcherait. –
Vous pouvez écrire un proc stockée qui effectue la suppression et l'appeler de LINQ. Une suppression basée sur un ensemble est probablement plus rapide dans l'ensemble, mais si elle affecte trop d'enregistrements, vous risquez de provoquer des problèmes de verrouillage et vous aurez peut-être besoin d'un hybride de boucles d'enregistrements (2000 à la fois). lieu de départ si vous trouvez que le delta basé sur l'ensemble prend si longtemps qu'il affecte d'autres utilisations de la table) pour faire la suppression.
Un temps, j'ai écrit une série d'articles en 4 parties (parties 1, 2, 3 et 4) couvrant modifions en vrac (avec une seule commande) dans le Entity Framework. Bien que l'objectif de cette série soit la mise à jour, vous pouvez certainement utiliser les principes impliqués pour effectuer la suppression.
Donc, vous devriez être capable d'écrire quelque chose comme ceci:
var query = from c in ctx.Customers
where c.SalesPerson.Email == "..."
select c;
query.Delete();
Tout ce que vous devez faire est de mettre en œuvre la méthode d'extension Supprimer(). Voir la série post pour obtenir des conseils sur la façon ...
Hope this helps
Excellente série. L'écriture d'une méthode d'extension Delete() basée sur ceci sera triviale. –
Serait bien d'avoir un exemple de code pour cela ici si quelqu'un l'a! – jocull
Un tas de méthodes d'extension (y compris une suppression par lots) peut être trouvé ici: https://github.com/loresoft/EntityFramework.Extended – Soliah
Les réponses que je vois ici sont à Sql Linq
DeleteAllOnSubmit fait partie de System.Data.Linq et Itableau qui est Linq to Sql
Cela ne peut pas être fait avec Entity Framework.
Après avoir dit tout ce que je n'ai pas une solution, mais encore signalerai quand je fais
using (var context = new DatabaseEntities())
{
// delete existing records
context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
}
+1 - Il est agréable de voir un exemple de code pour exécuter du code SQL en utilisant EF –
Je réalise que c'est probablement le seul moyen de le faire, à moins de créer une procédure stockée, mais cela ressemble à tricher =). Maintenant que j'utilise ceci, je suis tenté de l'utiliser dans plusieurs autres endroits pour éviter les bizarreries d'EF - comme les jointures complexes à gauche et les sauvegardes groupées ..... :) – Losbear
+! ... lors de l'utilisation d'une base de données , vous trouverez que l'outil que vous voulez est un tournevis .. EF est juste un autre marteau. – gbjbaanb
données via le Suppression Entity Framework repose sur l'utilisation de la méthode DeleteObject. Vous pouvez appeler cette méthode sur le EntityCollection pour la classe d'entité que vous souhaitez supprimer ou sur le ObjectContext dérivé. Voici un exemple simple:
NorthwindEntities db = new NorthwindEntities();
IEnumerable<Order_Detail> ods = from o in db.Order_Details
where o.OrderID == 12345
select o;
foreach (Order_Detail od in ods)
db.Order_Details.DeleteObject(od);
db.SaveChanges();
Ce n'est pas "Bulk Delete" cependant. – Nuzzolilo
Pour ceux qui utilisent EF6 et que vous souhaitez exécuter la ligne requête SQL pour la suppression:
using (var context = new DatabaseEntities())
{
// delete existing records
context.Database.ExecuteSqlCommand("DELETE FROM YOURTABLE WHERE CustomerID = @id", idParameter);
}
Cela a fonctionné pour moi dans EF 5 mais j'ai dû utiliser @ p0 pour le param.Ce qui est sympa, c'est qu'il fournit une vérification des paramètres de type safe dans le sql généré: donc dans EF5, cela fonctionnerait: context.Database.ExecuteSqlCommand ("SUPPRIMER FROM YOURTABLE O Customer CustomerID = @ p0", idParameter); \ @ p1 pour le param suivant, etc ... –
je ferais quelque chose comme:
var recordsToDelete = (from c in db.Candidates_T where c.MyField == null select c).ToList<Candidates_T>();
if(recordsToDelete.Count > 0)
{
foreach(var record in recordsToDelete)
{
db.Candidate_T.DeleteObject(record);
db.SaveChanges();
}
}
Je ne pense pas qu'il y ait un moyen de le faire sans boucle puisque Entity Framework fonctionne avec les Entités et la plupart du temps, cela signifie la collection d'objets.
Dans cet exemple, les enregistrements sont supprimés et, un par un, ils sont attachés à l'ensemble de résultats, puis demandés à être supprimés. Ensuite, j'ai 1 enregistrer les changements.
using (BillingDB db = new BillingDB())
{
var recordsToDelete = (from i in db.sales_order_item
where i.sales_order_id == shoppingCartId
select i).ToList<sales_order_item>();
if(recordsToDelete.Count > 0)
{
foreach (var deleteSalesOrderItem in recordsToDelete)
{
db.sales_order_item.Attach(deleteSalesOrderItem);
db.sales_order_item.Remove(deleteSalesOrderItem);
}
db.SaveChanges();
}
}
context.Entity.Where(p => p.col== id)
.ToList().ForEach(p => db.Entity.DeleteObject(p));
c'est méthode la plus rapide pour supprimer l'enregistrement de DB en utilisant EF
RemoveRange a été introduit en EF6, il peut supprimer une liste d'objets. Super facile.
var origins= (from po in db.PermitOrigins where po.PermitID == thisPermit.PermitID select po).ToList();
db.PermitOrigins.RemoveRange(origins);
db.SaveChanges();
Alors que cet extrait de code peut résoudre la question, [y compris une explication] (http: //meta.stackexchange .com/questions/114762/explaining-code-based-answers) aide vraiment à améliorer la qualité de votre message. Rappelez-vous que vous répondez à la question pour les lecteurs dans le futur, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. – DimaSan
Merci. J'ai mis à jour ceci pour être la réponse acceptée. –
EF 6 'RemoveRange' http://stackoverflow.com/a/21468165/1876572 – Eldho