Есть ли способ массового удаления группы объектов, соответствующих заданному запросу, в LINQ или LINQ-to-Entities? Единственные ссылки, которые я могу найти, устарели, и кажется глупым перебирать и вручную удалять все объекты, которые я хочу удалить.
Массовое удаление в LINQ to Entities
Ответы (14)
Вопрос старый (еще до того, как EF5 существовал). Для всех, кто использует EF5, EntityFramework.Extended сделает это в мгновение ока.
Некоторое время назад я написал серию блогов из 4 частей (Parts 1, 2, 3 и 4), охватывающий выполнение массовых обновлений (с помощью одной команды) в Entity Framework.
Хотя основное внимание в этой серии было уделено обновлению, вы определенно могли использовать соответствующие принципы для удаления.
Итак, у вас должно получиться написать что-то вроде этого:
var query = from c in ctx.Customers
where c.SalesPerson.Email == "..."
select c;
query.Delete();
Все, что вам нужно сделать, это реализовать метод расширения Delete (). Посмотрите серию сообщений, чтобы узнать, как ...
Надеюсь это поможет
Ответы, которые я здесь вижу, - это Linq to Sql
DeleteAllOnSubmit является частью System.Data.Linq и ITable, которые являются Linq to Sql
Это невозможно сделать с помощью Entity Framework.
Сказав все это, у меня еще нет решения, но я отправлю его, когда сделаю
Для тех, кто использует EF6 и хочет выполнить строковый SQL-запрос для удаления:
using (var context = new DatabaseEntities())
{
// delete existing records
context.Database.ExecuteSqlCommand("DELETE FROM YOURTABLE WHERE CustomerID = @id", idParameter);
}
RemoveRange был введен в EF6, он может удалять список объектов. Очень просто.
var origins= (from po in db.PermitOrigins where po.PermitID == thisPermit.PermitID select po).ToList();
db.PermitOrigins.RemoveRange(origins);
db.SaveChanges();
Я знаю метод DeleteAllOnSubmit для любой контекст данных, который удалит все записи в запросе. Должна быть некоторая оптимизация, поскольку удаляется много объектов. Хотя я не уверен.
Я не уверен, насколько это будет эффективно, но вы можете попробовать что-то вроде этого:
// 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();
Вы могли бы написать сохраненную процедуру, которая выполняет удаление и вызывать ее из LINQ. Удаление на основе набора, вероятно, в целом быстрее, но если оно затрагивает слишком много записей, вы можете вызвать проблемы с блокировкой, и вам может потребоваться гибрид перебора наборов записей (возможно, 2000 за раз, размер зависит от вашей структуры базы данных, но 2000 - это начальное место, если вы обнаружите, что дельта на основе набора занимает так много времени, что влияет на другое использование таблицы) для выполнения удаления.
Удаление данных через 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();
В этом примере я получаю записи для удаления и одну за другой прикрепляю их к набору результатов, а затем запрашиваю их удаление. Затем у меня есть 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();
}
}
context.Entity.Where(p => p.col== id)
.ToList().ForEach(p => db.Entity.DeleteObject(p));
это самый быстрый способ удалить запись из БД с помощью EF
Я бы сделал что-то вроде:
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, и в большинстве случаев это означает сбор объектов.
В текущем EF не реализована массовая операция.
Это просто так, как это было разработано командой entity framework. Декомпилятор ясно показывает, что делает 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 по-прежнему перебирает все объекты внутри и в памяти, что может быть очень неэффективным, если это много данных.
RemoveRange
EF также не выполняет массовое удаление.
- person Gert Arnold; 03.02.2021