有没有办法在LINQ或LINQ-to-Entities中批量删除与给定查询匹配的一堆对象?我能找到的唯一引用已经过时了,迭代并手动删除我想删除的所有对象似乎很愚蠢。
答案 0 :(得分:55)
前段时间我写了4部分博客系列(部件1,2,3和4),其中包括批量更新(使用一个命令)实体框架。
虽然该系列的重点是更新,但你绝对可以使用所涉及的原则进行删除。
所以你应该写下这样的东西:
var query = from c in ctx.Customers
where c.SalesPerson.Email == "..."
select c;
query.Delete();
您需要做的就是实现Delete()扩展方法。有关如何...的提示,请参阅帖子系列。
希望这有帮助
答案 1 :(得分:40)
using (var context = new DatabaseEntities())
{
// delete existing records
context.ExecuteStoreCommand("DELETE FROM YOURTABLE WHERE CustomerID = {0}", customerId);
}
答案 2 :(得分:29)
问题是旧问题(从EF5之前就存在)。对于使用EF5的任何人,EntityFramework.Extended都可以轻松完成。
答案 3 :(得分:6)
我在这里看到的答案是Linq to Sql
DeleteAllOnSubmit是System.Data.Linq和ITable的一部分,它是Linq to Sql
使用Entity Framework无法做到这一点。
说完所有这些我还没有解决方案,但会在我做的时候回复
答案 4 :(得分:4)
对于那些使用EF6并希望执行行SQL查询以进行删除的人:
using (var context = new DatabaseEntities())
{
// delete existing records
context.Database.ExecuteSqlCommand("DELETE FROM YOURTABLE WHERE CustomerID = @id", idParameter);
}
答案 5 :(得分:2)
我知道任何数据上下文的DeleteAllOnSubmit方法,它会删除查询中的所有记录。由于删除了很多对象,因此必须有一些优化。我不确定。
答案 6 :(得分: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();
答案 7 :(得分:1)
你可以写一个执行删除的存储过程并从LINQ调用它。基于集合的删除总体上可能更快,但如果它影响太多记录,则可能导致锁定问题,并且您可能需要循环记录集合(可能一次2000个,大小取决于您的数据库设计,但2000是一个如果您发现基于集合的delte需要很长时间才会影响表的其他用途,从而进行删除。
答案 8 :(得分:1)
通过Entity Framework删除数据依赖于使用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();
答案 9 :(得分:1)
我做的事情如下:
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();
}
}
我认为没有循环可以做到这一点,因为实体框架与实体一起工作,大多数时候,这意味着对象的集合。
答案 10 :(得分: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();
}
}
答案 11 :(得分:1)
context.Entity.Where(p => p.col== id)
.ToList().ForEach(p => db.Entity.DeleteObject(p));
这是使用EF
从DB中删除记录的最快方法答案 12 :(得分:1)
在EF6中引入了RemoveRange,它可以删除对象列表。超级容易。
var origins= (from po in db.PermitOrigins where po.PermitID == thisPermit.PermitID select po).ToList();
db.PermitOrigins.RemoveRange(origins);
db.SaveChanges();
答案 13 :(得分:0)
当前 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);
}
}
如您所见,EF 在内部循环遍历表的所有元素 - 通过调用 .ToList()
在内存中具体化。
如果您仍然想使用 EF 开箱即用的可能性来完成它,而不是提交 SQL 命令,您仍然可以通过一个小助手方法让您的生活更轻松。 语法
ctx.Table1.DeleteAllOnSubmit(ctx.Table1);
ctx.Table2.DeleteAllOnSubmit(ctx.Table2);
ctx.Table3.DeleteAllOnSubmit(ctx.Table3);
ctx.SubmitChanges();
我觉得不太好看。
这是我在 LinqPad 中写的一个例子,它简化了一点:
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();
}
如果你在做测试并且需要删除很多表,那么这个语法更容易处理。换句话说,这是一些为您提供方便的语法糖。但请记住,EF 仍会在内部和内存中循环遍历所有对象,如果数据量很大,这可能会非常低效。