LINQ to Entities'de toplu silme


82

LINQ veya LINQ-to-Entities'de belirli bir sorguyla eşleşen bir grup nesneyi toplu olarak silmenin herhangi bir yolu var mı? Bulabildiğim tek referanslar güncel değil ve kaldırmak istediğim tüm nesneleri yinelemek ve manuel olarak silmek aptalca görünüyor.

Yanıtlar:



53

Bir süre önce Entity Framework'te toplu güncellemeler (tek komutla) yapmayı kapsayan 4 bölümlük bir blog dizisi ( 1 , 2 , 3 ve 4 ) yazdım .

Bu serinin odak noktası güncelleme iken, silmek için kesinlikle ilgili ilkeleri kullanabilirsiniz.

Yani şöyle bir şey yazabilmelisiniz:

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

query.Delete();

Tek yapmanız gereken, Delete () uzantı yöntemini uygulamaktır. Nasıl yapılacağına dair ipuçları için gönderi serisine bakın ...

Bu yardımcı olur umarım


17
Kimse varsa, burada bunun için bir kod örneğinin olması güzel olurdu!
jocull

1
Bir grup uzatma yöntemi (toplu silme dahil) burada bulunabilir: github.com/loresoft/EntityFramework.Extended
Soliah

1
Dikkat edin github.com/loresoft/EntityFramework.Extended , EF5'e bağımlıdır, bunu yüklemek için Nuget Paket Yöneticisi Konsolu'nu kullanırsanız, sizden EF5
Paul Zahra

1
Gerçekten yardımcı olmuyor - Bir Sil komutunun çalışan bir örneğini görmek istiyorum, kendi kodumu üretim kodunda nasıl uygulayacağımı ve muhtemelen bir şeyi bozacağımı "tahmin etmek" istemiyorum. -1
nuzzolilo

27
Hm ... yani sorunun cevabı, belirli cevabı izleyiciye sunmak yerine 4 blog gönderisine yönlendirmek.
DeepSpace101

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

3
+1 - EF kullanarak SQL kodunun nasıl çalıştırılacağına dair bir kod örneği görmek güzel
Carlos P

2
Bunun muhtemelen bunu yapmanın tek yolu olduğunu anlıyorum, saklı yordam oluşturmanın dışında, ancak bu hile gibi geliyor =). Şimdi bunu kullandığıma göre, onu EF'nin tuhaf lol'ını (karmaşık sol birleşimler ve grup bys gibi) cicumvent etmek için başka yerlerde de kullanmak isterim ..... :)
Losbear

+! ... DB kullanırken, istediğiniz aletin bir tornavida olduğunu göreceksiniz .. EF sadece başka bir çekiçtir.
gbjbaanb

2
Biraz dezavantajı: Artık geliştirme ortamıyla bağlantısı kesilmiş bir veritabanı komutunuz var. Bu SQL sütunlar için veritabanına bir değişiklik yüzden şiddetle yazılan değil vurgulanır olmayacak Visual Studio
Ian

7

Burada gördüğüm cevaplar Linq to Sql

DeleteAllOnSubmit, System.Data.Linq'in bir parçasıdır ve Linq to Sql olan ITable'dır.

Bu, Entity Framework ile yapılamaz.

Bunların hepsini henüz bir çözümüm olmadığını söyledim, ancak yaptığımda geri göndereceğim


5

EF6 kullanan ve silmek için satır SQL sorgusu yürütmek isteyenler için:

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

1
Bu benim için EF 5'te çalıştı ama param için @ p0 kullanmak zorunda kaldım. Güzel olan, oluşturulan sql'de tür güvenli param denetimi sağlamasıdır: yani EF5'te bu işe yarar: context.Database.ExecuteSqlCommand ("DELETE FROM YOURTABLE WHERE WHERE = @ p0", idParameter); \ @ p1 sonraki parametre vb. için ...
Nathan Prather

3

RemoveRange, EF6'da tanıtıldı, nesnelerin bir listesini kaldırabilir. Çok kolay.

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

1
Bu kod parçacığı soruyu çözebilirken, bir açıklama eklemek, yayınınızın kalitesini artırmaya gerçekten yardımcı olur. Gelecekte okuyucular için soruyu yanıtladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceklerini unutmayın.
DimaSan

2

Sorgudaki tüm kayıtları silecek herhangi bir veri bağlamının DeleteAllOnSubmit yöntemini biliyorum . Birçok nesne silindiğinden, altında bazı optimizasyonların olması gerekir. Çok da emin değilim.


3
Aslında herhangi bir optimizasyon yapılmamaktadır. Oluşturulan SQL, sorgunuzla eşleşen tüm nesneleri numaralandırır, ardından bunları silmek için manuel olarak yineler. Verilen yineleme, kodunuz yerine DB'de gerçekleşir, ancak yine de yalnızca içeriğini silmek için gereksiz yere bir sonuç kümesi oluşturuyorsunuz - bu, oluşturulan basit bir "DELETE FROM table WHERE foo = bar" dan çok daha kötüdür. sonuç kümesi yok ve tabloyu yalnızca bir kez kapsar.
Benjamin Pollack

2

Ne kadar verimli olacağından emin değilim, ama şöyle bir şey deneyebilirsin:

// 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
Bu, sorguyla eşleşen tüm öğelerin yinelenmesiyle sonuçlanır; bunu kodunuzda değil, yalnızca DB'de yapar. Daha verimli, ancak yine de ideal bir çözüm olmaktan uzak.
Benjamin Pollack

3
Bunu yapmayı düşünmemin diğer tek yolu, myDataContext.ExecuteCommand ("DELETE ..."); yapmaktır. İdeal olmaktan da uzak, ama işe yarayacak.
Scott Anderson

1

Silmeyi yapan ve onu LINQ'dan çağıran depolanmış bir işlem yazabilirsiniz. Küme tabanlı silme muhtemelen genel olarak daha hızlıdır, ancak çok fazla kaydı etkiliyorsa, kilitlenme sorunlarına neden olabilirsiniz ve kayıt kümeleri arasında döngü oluşturmaya ihtiyaç duyabilirsiniz (belki bir seferde 2000, boyut veritabanı tasarımınıza bağlıdır, ancak 2000 başlangıç ​​noktası, küme tabanlı delte'nin çok uzun sürdüğünü fark ederseniz, silme işlemini yapmak için tablonun diğer kullanımını etkiler.


1

Entity Framework aracılığıyla verileri silmek, DeleteObject yöntemini kullanmaya dayanır. Bu yöntemi, silmek istediğiniz varlık sınıfı için EntityCollection veya türetilmiş ObjectContext üzerinde çağırabilirsiniz. İşte basit bir örnek:

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

Bu, "Toplu Silme" değildir.
nuzzolilo

1

Bu örnekte, silinecek kayıtları alıyorum ve bunları birer birer sonuç kümesine ekledikten sonra kaldırılmasını talep ediyorum. Sonra 1 kaydetme değişikliğim var.

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

Bunlar, EF kullanarak DB'den kayıt silmek için en hızlı yöntemdir


0

Şöyle bir şey yapardım:

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 Varlıklar ile çalıştığı için döngü olmadan bunu yapmanın bir yolu olduğunu düşünmüyorum ve çoğu zaman bu nesnelerin toplanması anlamına geliyor.


Yaptıklarınızı da paylaşabilirsiniz. Teşekkürler.
G Jeny Ramirez

@G Jeny Ramirez çözümümü ekledi.
Demodave

2
@GJennyRamirez de sizin örneğinizde Değişiklikleri defalarca kaydediyorsunuz ki bence bunu foreach döngüsünden
çıkarabilir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.