LINQ中对实体的批量删除


Answers:



53

前一段时间,我写了一个博客博客系列文章(第1部分,第2部分,第3部分和第4部分),共4部分,内容涉及在Entity Framework中使用一个命令进行批量更新。

尽管该系列的重点是更新,但是您绝对可以使用所涉及的原理进行删除。

因此,您应该能够编写如下内容:

var query = from c in ctx.Customers
            where c.SalesPerson.Email == "..."
            select c;

query.Delete();

您需要做的就是实现Delete()扩展方法。请参阅帖子系列以获取有关如何...的提示。

希望这可以帮助


17
如果有人在这里有一个代码示例,将是一件很高兴的事情!
jocull 2012年

1
一堆扩展方法(包括批量删除)可以在这里找到:github.com/loresoft/EntityFramework.Extended
Soliah's

1
当心github.com/loresoft/EntityFramework.Extended对EF5有依赖性,如果您使用Nuget软件包管理器控制台进行安装,它将不要求您安装EF5
Paul Zahra

1
它并没有真正的帮助-我想看到一个Delete命令的工作示例,而不是“猜测”如何在生产代码中实现自己的代码并可能搞砸了一些东西。-1
nuzzolilo

27
嗯...所以问题的答案是重定向到4个博客文章,而不是向观众展示具体答案。
DeepSpace101

41
    using (var context = new DatabaseEntities())
    {
        // delete existing records
        context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
    }

3
+1-很高兴看到如何使用EF执行SQL代码的代码示例
Carlos P

2
我意识到,这可能是唯一的方法,除了创建存储过程之外,但这就像作弊=)。现在,我正在使用它,我很想在其他几个地方使用它来阻止EF的古怪大声笑-例如复杂的左连接和分组
bys

+!...使用DB时,您会发现所需的工具是螺丝刀。EF只是另一把锤子。
gbjbaanb

2
不利的一面:您现在拥有一个与开发环境断开连接的数据库命令。它不是强类型的,因此在Visual Studio中不会突出显示此SQL中的列对数据库所做的更改
Ian

7

我在这里看到的答案是Linq to Sql

DeleteAllOnSubmit是System.Data.Linq和ITable的一部分,而ITable是SQL的Linq

使用实体框架无法做到这一点。

说了所有这些,我还没有解决方案,但是当我这样做时会回发


5

对于那些使用EF6并希望执行行SQL查询以进行删除的用户:

using (var context = new DatabaseEntities())
{
    // delete existing records
    context.Database.ExecuteSqlCommand("DELETE FROM YOURTABLE WHERE CustomerID = @id", idParameter);
}

1
这在EF 5中对我有用,但是我必须使用@ p0作为参数。很好的是,它在生成的sql中提供了类型安全的参数检查:因此在EF5中,它将起作用:context.Database.ExecuteSqlCommand(“从您的表中删除,客户ID = @ p0”,idParameter);\ @ p1用于下一个参数,等等...
内森·普拉瑟

3

RemoveRange是EF6中引入的,它可以删除对象列表。超级容易。

var origins= (from po in db.PermitOrigins where po.PermitID == thisPermit.PermitID select po).ToList();
db.PermitOrigins.RemoveRange(origins);
db.SaveChanges();

1
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
DimaSan '17

2

我知道任何数据上下文的DeleteAllOnSubmit方法,它将删除查询中的所有记录。由于要删除许多对象,因此必须进行一些优化。我不确定。


3
实际上,没有执行任何优化。生成的SQL枚举与查询匹配的所有对象,然后手动对其进行迭代以将其删除。当然,迭代发生在数据库中,而不是代码中,但是您仍在不必要地构建结果集以删除其内容,这远比构建简单的“从表中删除WHERE foo = bar”更糟糕。没有结果集,仅覆盖一次表格。
本杰明·波拉克

2

我不确定效率如何,但是您可以尝试执行以下操作:

// 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();

1
最终仍然要遍历所有与查询匹配的元素。它只是在数据库上执行,而不是在您的代码中执行。效率更高,但离理想解决方案还差得很远。
本杰明·波拉克

3
那么,我认为可以做的唯一另一种方法是执行myDataContext.ExecuteCommand(“ DELETE ...”);。同样,它也远非理想,但确实可行。
斯科特·安德森

1

您可以编写一个存储过程来执行删除操作,然后从LINQ中调用它。基于集合的删除总体上可能更快,但是如果影响太多的记录,则可能导致锁定问题,并且可能需要循环浏览记录集(一次可能是2000,其大小取决于数据库设计,但2000是起始位置(如果您发现基于集合的delte花费了很长时间,这会影响表的其他使用)进行删除。


1

通过实体框架删除数据依赖于使用DeleteObject方法。您可以在要删除的实体类的EntityCollection或派生的ObjectContext上调用此方法。这是一个简单的示例:

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();

那不是“批量删除”。
nuzzolilo

1

在此示例中,我删除了记录,然后将它们一个接一个地附加到结果集,然后请求将其删除。然后我有1个保存更改。

    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();
      } 
    }


0

我会做类似的事情:

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();
    }
}   

我不认为没有循环就可以做到这一点,因为Entity Framework与Entities一起使用,并且在大多数情况下,这意味着对象的集合。


您也可以分享您所做的事情。谢谢。
G詹妮·拉米雷斯

@G Jeny Ramirez添加了我的解决方案。
Demodave

2
@GJennyRamirez在您的示例中,您还保存了多次更改,我认为您可以将其拉出foreach循环并执行一次
Demodave
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.