C# LINQ中的批量删除到实体

C# LINQ中的批量删除到实体,c#,database,linq,entity-framework,linq-to-entities,C#,Database,Linq,Entity Framework,Linq To Entities,是否有任何方法可以批量删除与LINQ或LINQ中的给定查询与实体匹配的一组对象?我能找到的唯一引用已经过时,而且迭代并手动删除所有我希望删除的对象似乎很愚蠢。我知道任何数据上下文的方法都会删除查询中的所有记录。由于删除了很多对象,因此必须进行一些优化。不过我不确定。我不确定它的效率,但您可以尝试以下方法: // deletes all "People" with the name "Joe" var mypeople = from p in myDataContext.People

是否有任何方法可以批量删除与LINQ或LINQ中的给定查询与实体匹配的一组对象?我能找到的唯一引用已经过时,而且迭代并手动删除所有我希望删除的对象似乎很愚蠢。

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

我不确定它的效率,但您可以尝试以下方法:

// 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();
var query = from c in ctx.Customers
            where c.SalesPerson.Email == "..."
            select c;

query.Delete();

您可以编写一个执行删除的存储过程,并从LINQ调用它。总体而言,基于集合的删除速度可能更快,但如果它影响太多记录,则可能会导致锁定问题,并且可能需要混合循环记录集合(一次可能是2000个,大小取决于数据库设计,但如果您发现基于集合的删除耗时太长,会影响表的其他使用,则2000是一个起点)执行删除操作

不久前,我写了一个由4部分组成的博客系列(Parts,and),介绍在实体框架中进行批量更新(使用一个命令)

虽然该系列的重点是更新,但您完全可以使用所涉及的原则进行删除

所以你应该能写下这样的东西:

// 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();
var query = from c in ctx.Customers
            where c.SalesPerson.Email == "..."
            select c;

query.Delete();
您所需要做的就是实现Delete()扩展方法。有关如何


希望这有帮助

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

DeleteAllOnSubmit是System.Data.Linq的一部分,ITable是Linq to Sql的一部分

这不能用实体框架来完成


说到这里,我还没有一个解决方案,但是当我通过实体框架删除数据时,我将返回使用DeleteObject方法。可以在要删除的实体类的EntityCollection上或在派生的ObjectContext上调用此方法。下面是一个简单的例子:

    using (var context = new DatabaseEntities())
    {
        // delete existing records
        context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
    }
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();
NorthwindEntities db=新的NorthwindEntities();
IEnumerable ods=从o开始,以db.Order\u详细信息为单位
其中o.OrderID==12345
选择o;
foreach(订单详细信息ods中的od)
db.Order_Details.DeleteObject(od);
db.SaveChanges();

这是一个老问题(在EF5出现之前)。对于使用EF5的任何人,都可以快速执行此操作。

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

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

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();
    }
}   
var recordsToDelete=(从db.Candidates中的c开始,其中c.MyField==null选择c);
如果(recordsToDelete.Count>0)
{
foreach(recordsToDelete中的var记录)
{
db.Candidate\u.DeleteObject(记录);
db.SaveChanges();
}
}   

我不认为没有循环就可以做到这一点,因为实体框架与实体一起工作,大多数情况下,这意味着对象的收集。

在本例中,我将删除记录,并将其逐个附加到结果集,然后请求将其删除。然后我有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();
      } 
    }
使用(BillingDB=new BillingDB())
{
var recordsToDelete=(来自db.sales\u order\u项目中的i
其中i.sales\u order\u id==shoppingCartId
选择i.ToList();
如果(recordsToDelete.Count>0)
{
foreach(recordsToDelete中的var deleteSalesOrderItem)
{                  
db.sales\u order\u item.Attach(删除SalesOrderItem);
db.sales\u order\u item.Remove(删除SalesOrderItem);
}
db.SaveChanges();
} 
}

这是使用EF从数据库中删除记录的最快方法。RemoveRange是在EF6中引入的,它可以删除对象列表。超级容易

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

当前EF中未实施批量操作。

这正是实体框架团队设计的方式。反编译器清楚地显示EF在内部执行的操作:

public void DeleteAllOnSubmit<TSubEntity>(IEnumerable<TSubEntity> entities) 
where TSubEntity : TEntity
{
    if (entities == null)
    {
        throw Error.ArgumentNull("entities");
    }
    CheckReadOnly();
    context.CheckNotInSubmitChanges();
    context.VerifyTrackingEnabled();
    foreach (TSubEntity item in entities.ToList())
    {
        TEntity entity = (TEntity)(object)item;
        DeleteOnSubmit(entity);
    }
}
在我看来不太好看

下面是我写的一个例子,它稍微简化了一点:

void Main()
{
    var ctx = this;

    void DeleteTable<T>(System.Data.Linq.Table<T> tbl, bool submitChanges = false)
    where T : class
    {
        tbl.DeleteAllOnSubmit(tbl);
        if (submitChanges) ctx.SubmitChanges();
    }
    
    DeleteTable(ctx.Table1);
    DeleteTable(ctx.Table2);
    DeleteTable(ctx.Table3);
        
    ctx.SubmitChanges();
}
void Main()
{
var ctx=此;
void deletetetable(System.Data.Linq.Table tbl,bool submitChanges=false)
T:在哪里上课
{
tbl.DeleteAllOnSubmit(tbl);
if(submitChanges)ctx.submitChanges();
}
删除表(ctx.Table1);
删除表(ctx.表2);
删除表(ctx.表3);
ctx.SubmitChanges();
}

如果您正在进行测试,并且需要删除很多表,那么这种语法更容易处理。换句话说,这是一些语法上的糖分,方便你使用。但请记住,EF仍然在内部和内存中循环所有对象,如果数据量很大,这可能会非常低效。

这仍然会迭代匹配查询的所有元素;它只在DB上执行,而不是在代码中执行。效率更高,但离理想的解决方案还有一段距离。那么,我唯一能想到的其他方法就是使用myDataContext.ExecuteCommand(“删除…”);。这也很不理想,但它会起作用。实际上没有进行任何优化。生成的SQL枚举与查询匹配的所有对象,然后手动迭代以删除它们。当然,迭代是在数据库中进行的,而不是在代码中,但是您仍然不必要地构建一个结果集,仅仅是为了删除其内容——这比简单的“从表中删除foo=bar”要糟糕得多,后者不构建结果集,只覆盖表一次。如果有人有代码示例,那么在这里就很好了!在这里可以找到一系列扩展方法(包括批量删除):当心对EF5有依赖性,如果您使用Nuget Package manager控制台安装它,它将在不要求您安装EF5的情况下安装它。它并没有真正的帮助-我想看一个delete命令的工作示例,而不是“猜测”如何在生产代码中实现我自己的代码以及