Cara menghapus objek dengan id dengan kerangka entitas

105

Sepertinya saya harus mengambil objek sebelum saya menghapusnya dengan kerangka entitas seperti di bawah ini

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

context.DeleteObject(customer);

context.Savechanges();

Jadi saya perlu mengakses database dua kali. Apakah ada cara yang lebih mudah?

Jeff
sumber
j.mp/f0x0Bh adalah jawaban Anda. Ini adalah cara yang bagus dan umum untuk melakukannya
BritishDeveloper

Jawaban:

93

Dalam Entity Framework 6 tindakan hapus adalah Remove. Berikut ini contohnya

Customer customer = new Customer () { Id = id };
context.Customers.Attach(customer);
context.Customers.Remove(customer);
context.SaveChanges();
dwkd
sumber
16
Kenapa Attach? Mengapa tidak adil Removedan SaveChanges?
runeks
3
Anda harus melampirkan entitas Anda dalam konteks karena jika Anda tidak melakukannya, Anda akan menerima pesan kesalahan saat menghapus. EF dapat menghapus entitas dalam konteks ini hanya
Pierre-Luc
3
@ runeks menurut manual entitas harus ada dalam konteks sebelum operasi Hapus dapat dilakukan. Lihat di sini docs.microsoft.com/en-us/dotnet/api/…
dwkd
1
saya tidak menggunakan melampirkan, dan wajan baik
ILIAS M. DOLAPO
58

Sama seperti @Nix dengan sedikit perubahan untuk diketik dengan kuat:

Jika Anda tidak ingin menanyakannya, buat saja entitas, lalu hapus.

                Customer customer = new Customer () { Id = id };
                context.Customers.Attach(customer);
                context.Customers.DeleteObject(customer);
                context.SaveChanges();
Sawan
sumber
7
Tidak sempurna karena memunculkan pengecualian jika objek hilang: "DbUpdateConcurrencyException: Pernyataan pembaruan, sisipkan, atau hapus penyimpanan memengaruhi jumlah baris yang tidak terduga (0)." Saya ingin mengabaikan ini, seperti pernyataan DELETE.
Dunc
maaf, ini menyebabkan validasi yang tidak diperlukan dan diharapkan selalu!
Hamed Zakery Miab
32

Pertanyaan serupa di sini .

Dengan Entity Framework ada EntityFramework-Plus (pustaka ekstensi).
Tersedia di NuGet. Kemudian Anda bisa menulis sesuatu seperti:

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

Ini juga berguna untuk penghapusan massal.

acarlon.dll
sumber
36
Ini menentang alasan bahwa ini bukan bagian dari perpustakaan inti EF sekarang.
nathanchere
1
@FerretallicA - setuju.
acarlon
2
metode ini adalah penggunaan usang: context.Users.Where (user => user.Id == id) .Delete ();
Manuel
Itu tidak bekerja dengan Azure SQL DataWarehouse karena kesalahan "Klausa FROM saat ini tidak didukung dalam pernyataan DELETE.". Tetapi SQL mentah seperti dalam jawaban Jonik berfungsi.
Michael Freidgeim
1
Apakah context.SaveChanges () diperlukan?
Tomas Kubes
23

Jika Anda tidak ingin menanyakannya, buat saja entitas, lalu hapus.

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

Saya menggunakan kode berikut di salah satu proyek saya:

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

Dengan cara ini, ini akan meminta database dua kali hanya jika terjadi pengecualian saat mencoba menghapus item dengan ID yang ditentukan. Kemudian jika item tidak ditemukan, itu mengembalikan pesan yang berarti; jika tidak, itu hanya mengembalikan pengecualian (Anda dapat menangani ini dengan cara yang lebih sesuai dengan kasus Anda menggunakan blok tangkapan yang berbeda untuk jenis pengecualian yang berbeda, tambahkan lebih banyak pemeriksaan khusus menggunakan blok if dll.).

[Saya menggunakan kode ini dalam proyek MVC .Net Core / .Net Core dengan Entity Framework Core.]

demonicdaron
sumber
2

Kueri sql mentah adalah cara tercepat yang saya kira

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.
   }
}
Jonik
sumber
19
Ini mengalahkan tujuan penggunaan fungsi objek yang sangat diketik di EF.
LawMan
4
Ini membahayakan uang tunai identitas EF. Setelah EF ini masih akan mengembalikan entitas Anda yang dihapus.
epox
1
Ia bekerja dengan Azure SQL DataWarehouse, ketika solusi lain tidak.
Michael Freidgeim
1
Jika Anda melakukan ini, Anda mungkin juga tidak menggunakan ORM. Saya membayangkan bahwa ini akan membahayakan cache EF.
Storm Muller
Gaya ini rentan terhadap serangan SQL Injection. Dalam contoh khusus ini Anda dilindungi karena variabelnya adalah bilangan bulat, tetapi jangan pernah menggunakan pola ini dengan variabel string.
thelem
2

Jawaban dwkd sebagian besar bekerja untuk saya di inti Kerangka Kerja Entitas, kecuali ketika saya melihat pengecualian ini:

InvalidOperationException: Instance dari jenis entitas 'Pelanggan' tidak dapat dilacak karena instance lain dengan nilai kunci yang sama untuk {'Id'} sudah dilacak. Saat melampirkan entitas yang ada, pastikan bahwa hanya satu instance entitas dengan nilai kunci tertentu yang dilampirkan. Pertimbangkan untuk menggunakan 'DbContextOptionsBuilder.EnableSensitiveDataLogging' untuk melihat nilai kunci yang bentrok.

Untuk menghindari pengecualian, saya memperbarui kode:

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();
Jeffrey Rennie
sumber
2

Versi yang lebih kecil (jika dibandingkan dengan yang sebelumnya):

var customer = context.Find(id);
context.Delete(customer);
context.SaveChanges();
Luis Gouveia
sumber
Berikan beberapa konteks pada cuplikan kode ini, dan mungkin beberapa penjelasan tentang apa yang lebih baik daripada jawaban lain yang tersisa dalam dekade terakhir.
miken32
1

Jawaban ini sebenarnya diambil dari mata kuliah Scott Allen yang bertajuk ASP.NET MVC 5 Fundamentals. Saya pikir saya akan berbagi karena menurut saya ini sedikit lebih sederhana dan lebih intuitif daripada jawaban mana pun di sini. Perhatikan juga menurut Scott Allen dan pelatihan lain yang telah saya lakukan, metode temukan adalah cara yang dioptimalkan untuk mengambil sumber daya dari database yang dapat menggunakan caching jika sudah diambil. Dalam kode ini, koleksi mengacu pada DBSet objek. Objek dapat berupa tipe objek umum apa pun.

        var object = context.collection.Find(id);  
        context.collection.Remove(object);
        context.SaveChanges();
andy_coder
sumber