Xóa hàng loạt trong LINQ đối với các thực thể


82

Có cách nào để xóa hàng loạt đối tượng khớp với một truy vấn nhất định trong LINQ hoặc LINQ-to-Entities không? Các tham chiếu duy nhất mà tôi có thể tìm thấy đã lỗi thời và có vẻ ngớ ngẩn khi lặp lại và xóa thủ công tất cả các đối tượng tôi muốn xóa.

Câu trả lời:


30

Câu hỏi là một câu hỏi cũ (từ trước khi EF5 tồn tại). Đối với bất kỳ ai đang sử dụng EF5, EntityFramework.Extended sẽ thực hiện điều này trong tích tắc.


53

Một thời gian trước, tôi đã viết một loạt blog 4 phần (Phần 1 , 2 , 34 ) bao gồm cập nhật hàng loạt (với một lệnh) trong Entity Framework.

Trong khi trọng tâm của loạt bài đó là cập nhật, bạn chắc chắn có thể sử dụng các nguyên tắc liên quan để xóa.

Vì vậy, bạn sẽ có thể viết một cái gì đó như thế này:

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

query.Delete();

Tất cả những gì bạn cần làm là triển khai phương thức mở rộng Delete (). Xem loạt bài đăng để biết gợi ý về cách ...

Hi vọng điêu nay co ich


17
Rất vui nếu có ai có mã mẫu này ở đây!
jocull

1
Bạn có thể tìm thấy một loạt các phương pháp mở rộng (bao gồm xóa hàng loạt) tại đây: github.com/loresoft/EntityFramework.Extended
Soliah

1
Hãy coi chừng github.com/loresoft/EntityFramework.Extended có một sự phụ thuộc vào EF5, nếu bạn sử dụng quản lý NuGet Package Console để cài đặt nó, nó sẽ không yêu cầu bạn cài đặt EF5
Paul Zahra

1
Nó không thực sự hữu ích - Tôi muốn xem một ví dụ hoạt động của lệnh Delete chứ không phải "đoán" cách triển khai mã lệnh của riêng tôi trong sản xuất và có thể làm hỏng điều gì đó. -1
nuzzolilo

27
Hm ... vì vậy câu trả lời cho câu hỏi là chuyển hướng đến 4 bài đăng trên blog thay vì trình bày câu trả lời cụ thể cho khán giả.
DeepSpace101

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

3
+1 - Rất vui được xem ví dụ mã về cách thực thi mã SQL bằng EF
Carlos P

2
Tôi nhận ra đây có lẽ là cách duy nhất để làm điều này, ngắn gọn là tạo một thủ tục được lưu trữ, nhưng điều này giống như gian lận =). Bây giờ mà tôi đang sử dụng này, tôi đang bị cám dỗ để sử dụng nó trong một số nơi khác để lol quirkiness cicumvent EF - như phức tạp trái tham gia và bys nhóm ..... :)
Losbear

+! ... khi sử dụng DB, bạn sẽ thấy rằng công cụ bạn muốn là một cái tuốc nơ vít .. EF chỉ là một cái búa khác.
gbjbaanb

2
Nhược điểm nhẹ: bây giờ bạn có một lệnh cơ sở dữ liệu bị ngắt kết nối khỏi môi trường phát triển. Nó không được đánh mạnh, vì vậy thay đổi đối với cơ sở dữ liệu cho các cột trong SQL này sẽ không được đánh dấu trong Visual Studio
Ian

7

Các câu trả lời tôi thấy ở đây là Linq to Sql

DeleteAllOnSubmit là một phần của System.Data.Linq và ITable là Linq to Sql

Điều này không thể được thực hiện với Entity Framework.

Đã nói tất cả những điều đó, tôi chưa có giải pháp nhưng sẽ đăng lại khi tôi thực hiện


5

Đối với những người sử dụng EF6 và muốn thực hiện truy vấn SQL hàng để xóa:

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

1
Điều này làm việc cho tôi trong EF 5 nhưng tôi phải sử dụng @ p0 cho tham số. Điều thú vị là nó cung cấp tính năng kiểm tra tham số an toàn kiểu trong sql được tạo: vì vậy trong EF5, điều này sẽ hoạt động: context.Database.ExecuteSqlCommand ("DELETE FROM YOURTABLE WHERE CustomerID = @ p0", idParameter); \ @ p1 cho thông số tiếp theo, v.v.
Nathan Prather

3

RemoveRange được giới thiệu trong EF6, nó có thể xóa danh sách các đối tượng. Siêu dễ dàng.

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

1
Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
DimaSan

2

Tôi biết về phương thức DeleteAllOnSubmit của bất kỳ ngữ cảnh dữ liệu nào sẽ xóa tất cả các bản ghi trong truy vấn. Phải có một số tối ưu hóa cơ bản vì rất nhiều đối tượng đang bị xóa. Tôi không chắc chắn mặc dù.


3
Thực sự không có bất kỳ tối ưu hóa nào được thực hiện. SQL được tạo liệt kê tất cả các đối tượng phù hợp với truy vấn của bạn, sau đó lặp lại theo cách thủ công để xóa chúng. Được cho là, việc lặp lại xảy ra trong DB, chứ không phải trong mã của bạn, nhưng bạn vẫn không cần thiết phải xây dựng một tập hợp kết quả chỉ để xóa nội dung của nó - còn tệ hơn nhiều so với một "XÓA khỏi bảng WHERE foo = bar" đơn giản, được xây dựng không có kết quả đặt và chỉ bao gồm bảng một lần.
Benjamin Pollack

2

Tôi không chắc nó sẽ hiệu quả như thế nào, nhưng bạn có thể thử một cái gì đó như sau:

// 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
Điều đó vẫn kết thúc lặp lại trên tất cả các phần tử phù hợp với truy vấn; nó chỉ làm như vậy trên DB, chứ không phải trong mã của bạn. Hiệu quả hơn, nhưng vẫn chưa phải là một giải pháp lý tưởng.
Benjamin Pollack

3
Cách duy nhất tôi có thể nghĩ để làm điều đó là thực hiện myDataContext.ExecuteCommand ("DELETE ...") ;. Xa lý tưởng, cũng có, nhưng nó sẽ hoạt động.
Scott Anderson

1

YOu có thể viết một proc được lưu trữ để thực hiện việc xóa và gọi nó từ LINQ. Về tổng thể, xóa dựa trên tập hợp có thể nhanh hơn nhưng nếu nó ảnh hưởng đến quá nhiều bản ghi, bạn có thể gây ra sự cố khóa và bạn có thể cần kết hợp lặp qua các tập hợp bản ghi (có thể là 2000 cùng một lúc, kích thước phụ thuộc vào thiết kế cơ sở dữ liệu của bạn nhưng 2000 là một bắt đầu nếu bạn thấy lỗi dựa trên tập hợp mất quá nhiều thời gian để ảnh hưởng đến việc sử dụng bảng khác) để thực hiện xóa.


1

Việc xóa dữ liệu qua Khung thực thể dựa vào việc sử dụng phương pháp DeleteObject. Bạn có thể gọi phương thức này trên EntityCollection cho lớp thực thể mà bạn muốn xóa hoặc trên ObjectContext dẫn xuất. Đây là một ví dụ đơn giản:

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

Đó không phải là "Xóa hàng loạt".
nuzzolilo

1

Trong ví dụ này, tôi yêu cầu xóa các bản ghi, và từng người một đính kèm chúng vào tập kết quả rồi yêu cầu xóa chúng. Sau đó, tôi có 1 lần lưu thay đổi.

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

1
 context.Entity.Where(p => p.col== id)
               .ToList().ForEach(p => db.Entity.DeleteObject(p));

đây là phương pháp nhanh nhất để xóa bản ghi khỏi DB bằng EF


0

Tôi muốn làm một cái gì đó như:

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

Tôi không nghĩ có cách nào để làm điều đó mà không cần vòng lặp vì Entity Framework hoạt động với các Entity và hầu hết thời gian, điều này có nghĩa là tập hợp các đối tượng.


Bạn cũng có thể chia sẻ những gì bạn đã làm. Cảm ơn.
G Jeny Ramirez,

@G Jeny Ramirez Đã thêm giải pháp của tôi.
Demodave

2
@GJennyRamirez cũng trong ví dụ của bạn, bạn là savingChanges nhiều lần mà tôi nghĩ bạn có thể kéo ra rằng bên cạnh vòng lặp foreach và thực hiện một lần
Demodave
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.