Varlık çerçevesi ile kimliğe göre bir nesne nasıl silinir


105

Bana öyle geliyor ki, aşağıdaki gibi bir varlık çerçevesi ile silmeden önce bir nesneyi geri almam gerekiyor

var customer = context.Customers.First(c => c.Id == 1);

context.DeleteObject(customer);

context.Savechanges();

Bu yüzden veritabanına iki kez vurmam gerekiyor. Daha kolay bir yol var mı?


j.mp/f0x0Bh cevabınızdır. Bu, bunu yapmanın güzel ve genel bir yolu
BritishDeveloper

Yanıtlar:


94

Entity Framework 6'da silme eylemi Remove. İşte bir örnek

Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();

16
Neden Attach? Neden sadece Removeve değil SaveChanges?
runeks

3
Varlığınızı bağlama eklemelisiniz çünkü bunu yapmazsanız, kaldırırken bir hata alırsınız. EF, varlıkları yalnızca bu bağlamda kaldırabilir
Pierre-Luc

3
Kılavuza göre @runeks, Kaldırma işlemi gerçekleştirilmeden önce varlık bağlamda bulunmalıdır. Buraya bakın docs.microsoft.com/en-us/dotnet/api/…
dwkd


58

Kesinlikle yazılması gereken küçük bir değişiklikle @Nix ile aynı:

Sorgulamak istemiyorsanız, sadece bir varlık oluşturun ve ardından silin.

                Customer customer = new Customer () { Id = id };
                context.Customers.Attach(customer);
                context.Customers.DeleteObject(customer);
                context.SaveChanges();

7
Nesne eksikse bir istisna attığı için mükemmel değil: "DbUpdateConcurrencyException: Store update, insert veya delete ifadesi beklenmedik sayıda satırı (0) etkiledi." Bunu bir DELETE ifadesinin yapacağı gibi görmezden gelmesini istiyorum.
Dunc

üzgünüm, bu her zaman gerekli olmayan ve beklenen doğrulamaya neden olur!
Hamed Zakery Miab

32

Benzer soru burada .

Entity Framework ile EntityFramework-Plus (uzantı kitaplığı) vardır.
NuGet'te mevcuttur. O zaman şöyle bir şey yazabilirsiniz:

// DELETE all users which has been inactive for 2 years
ctx.Users.Where(x => x.LastLoginDate < DateTime.Now.AddYears(-2))
     .Delete();

Ayrıca, toplu silme işlemleri için de kullanışlıdır.


37
Şimdiye kadar bunun çekirdek EF kitaplığının bir parçası olmaması nedenine meydan okuyor.
nathanchere

1
@FerretallicA - kabul etti.
acarlon

2
bu yöntem eski kullanımdır: context.Users.Where (user => user.Id == id) .Delete ();
Manuel

"A FROM yan tümcesi şu anda bir DELETE deyiminde desteklenmiyor." Hatası nedeniyle Azure SQL DataWarehouse ile çalışmaz. Ama Jonik en olduğu gibi ham SQL cevap işler.
Michael Freidgeim

1
Context.SaveChanges () gerekli mi?
Tomas Kubes

23

Sorgulamak istemiyorsanız, sadece bir varlık oluşturun ve ardından silin.

Customer customer  = new Customer() {  Id = 1   } ; 
context.AttachTo("Customers", customer);
context.DeleteObject(customer);
context.Savechanges();

6

Projelerimden birinde aşağıdaki kodu kullanıyorum:

    using (var _context = new DBContext(new DbContextOptions<DBContext>()))
    {
        try
        {
            _context.MyItems.Remove(new MyItem() { MyItemId = id });
            await _context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            if (!_context.MyItems.Any(i => i.MyItemId == id))
            {
                return NotFound();
            }
            else
            {
                throw ex;
            }
        }
    }

Bu şekilde, yalnızca belirtilen kimliğe sahip öğeyi kaldırmaya çalışırken bir istisna meydana gelirse veritabanını iki kez sorgulayacaktır. Ardından öğe bulunmazsa anlamlı bir mesaj verir; aksi takdirde, istisnayı geri atar (bunu, farklı istisna türleri için farklı yakalama blokları kullanarak durumunuza daha uygun bir şekilde halledebilir, if bloklarını kullanarak daha fazla özel kontrol ekleyebilirsiniz vb.).

[Bu kodu Entity Framework Core ile bir MVC .Net Core / .Net Core projesinde kullanıyorum.]


2

Ham sql sorgusu sanırım en hızlı yoldur

public void DeleteCustomer(int id)
{
   using (var context = new Context())
   {
      const string query = "DELETE FROM [dbo].[Customers] WHERE [id]={0}";
      var rows = context.Database.ExecuteSqlCommand(query,id);
      // rows >= 1 - count of deleted rows,
      // rows = 0 - nothing to delete.
   }
}

19
Bu, EF'de güçlü biçimde yazılmış nesne işlevini kullanma amacını ortadan kaldırır.
LawMan

4
Bu, EF kimlik parasını tehlikeye atar. Bu EF'den sonra yine de silinmiş varlığınıza geri dönecektir.
epox

1
Diğer çözümler çalışmadığında Azure SQL DataWarehouse ile çalışır.
Michael Freidgeim

1
Bunu yapıyorsanız, bir ORM kullanmayabilirsiniz. Bunun EF önbelleğini tehlikeye atacağını hayal ediyorum.
Fırtına Muller

Bu tarz, SQL Injection saldırılarına karşı savunmasızdır. Bu özel örnekte, değişken bir tam sayı olduğu için korunuyorsunuz, ancak bu kalıbı asla bir dize değişkeniyle kullanmayın.
thelem

2

dwkd'nin cevabı, bu istisnayı gördüğüm durumlar dışında çoğunlukla Entity Framework çekirdeğinde benim için çalıştı:

InvalidOperationException: "Müşteri" varlık türü örneği, {'Id'} için aynı anahtar değerine sahip başka bir örnek zaten izlendiğinden izlenemiyor. Mevcut varlıkları iliştirirken, belirli bir anahtar değerine sahip yalnızca bir varlık örneğinin eklendiğinden emin olun. Çakışan anahtar değerlerini görmek için 'DbContextOptionsBuilder.EnableSensitiveDataLogging' kullanmayı düşünün.

İstisnadan kaçınmak için kodu güncelledim:

Customer customer = context.Customers.Local.First(c => c.Id == id);
if (customer == null) {
    customer = new Customer () { Id = id };
    context.Customers.Attach(customer);
}
context.Customers.Remove(customer);
context.SaveChanges();

2

Daha küçük bir versiyon (öncekilerle karşılaştırıldığında):

var customer = context.Find(id);
context.Delete(customer);
context.SaveChanges();

Lütfen bu kod parçacığına biraz bağlam ve belki de son on yılda bırakılan diğer yanıtlardan daha iyi ne yaptığına dair biraz açıklama sağlayın.
miken32

1

Bu cevap aslında Scott Allen'ın ASP.NET MVC 5 Temelleri başlıklı kursundan alınmıştır. Paylaşacağımı düşündüm çünkü buradaki cevapların hepsinden biraz daha basit ve sezgisel olduğunu düşünüyorum. Ayrıca Scott Allen ve yaptığım diğer eğitimlere göre, bulma yöntemi, önceden alınmışsa önbelleğe almayı kullanabilen bir kaynağı veritabanından almak için optimize edilmiş bir yoldur. Bu kodda koleksiyon, nesnelerin DBSet'ini ifade eder. Nesne, herhangi bir genel nesne türü olabilir.

        var object = context.collection.Find(id);  
        context.collection.Remove(object);
        context.SaveChanges();
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.