Apakah OK untuk membuat objek Entity Framework DataContext dan membuangnya di blok menggunakan di setiap metode CRUD saya?

10

Saya sedang membangun aplikasi WPF yang mengimplementasikan fitur-fitur berikut:

  1. Ambil input pengguna dan baca data dari basis data
  2. melakukan beberapa perhitungan di atasnya
  3. Perlihatkan kepada pengguna dalam berbagai jenis tampilan dan tulis perubahan kembali ke db

Arsitektur yang diajukan: Database -> Kerangka Entitas -> Repositori -> Logika Bisnis -> Layanan Data -> ViewModel

Alasan untuk menggunakan arsitektur ini: Beberapa skenario hadir dalam aplikasi (Multiple view) dan beberapa database. Karenanya, saya bersedia menggunakan repositori di tengah untuk abstraksi.

Satu peringatan adalah bahwa konteksnya akan berumur panjang jika repositori diimplementasikan. Untuk mengatasinya, apakah boleh membuat konteks dan membuangnya dalam blok using () di masing-masing metode crud.?

jangan ragu untuk menyarankan pendekatan alternatif.

Potong langit
sumber
Lihat utas ini yang mirip dengan kueri Anda. stackoverflow.com/questions/21875816/…
Gopinath

Jawaban:

16

Gunakan satu objek DbContext per akses data atau transaksi.

DbContextadalah benda yang ringan; itu dirancang untuk digunakan sekali per transaksi bisnis. Membuat DbContextSingleton Anda dan menggunakannya kembali di seluruh aplikasi dapat menyebabkan masalah lain, seperti masalah konkurensi dan kebocoran memori.

DbContextpada dasarnya mengimplementasikan Satuan Kerja. Perlakukan sesuai.

Jangan buang objek DbContext.

Meskipun DbContextimplementasinya IDisposable, Anda tidak harus membuangnya secara manual, atau membungkusnya dalam usingpernyataan. DbContextmengelola hidupnya sendiri; ketika permintaan akses data Anda selesai, DbContextsecara otomatis akan menutup koneksi database untuk Anda.

Untuk memahami mengapa hal ini terjadi, pertimbangkan apa yang terjadi ketika Anda menjalankan pernyataan Linq pada koleksi entitas dari a DbContext. Jika Anda mengembalikan pemuatan malas IQueryabledari metode akses data Anda, Anda berdiri pipa yang sebenarnya tidak dieksekusi sampai klien memaksa beberapa data dari itu (dengan menelepon FirstOrDefault(), ToList()atau beralih di atasnya).

Bacaan Lebih Lanjut
Apakah saya harus selalu memanggil Buang () pada objek DbContext saya?
Mengapa Anda tidak harus menggunakan Singleton DataContexts di Entity Framework
Returning IEnumerable<T>vs. IQueryable<T>
Haruskah Repositori kembali IQueryable?

Robert Harvey
sumber
4
Meskipun saya yakin seseorang akan membuat semacam kasus luar biasa untuk ini, saya benar-benar tidak dapat membuat kasus penggunaan yang baik untuk mengembalikan IQ yang tidak terwujud dari kelas akses data Anda. Itu hanya memberikan kode panggilan kemampuan untuk menjangkau ke dalam akses data Anda (sesuatu yang mungkin tidak ada urusannya) dan mengacaukan berbagai hal. Yang sedang berkata, apakah itu benar-benar masalah besar untuk khawatir menggunakan usingblok? Atau apakah saya hanya tidak memikirkan beberapa kasus di mana menggunakan IQueryable seperti yang Anda sarankan akan sepadan dengan masalahnya?
Becuzz
@Becuzz: DbContextBertanggung jawab untuk mengelola masa hidupnya sendiri. Saran saya adalah membiarkannya melakukan itu; itu akan berfungsi apakah Anda menggunakan IQueryableatau IEnumerable. Kasus penggunaan yang paling jelas yang dapat saya pikirkan untuk pemuatan malas adalah di mana Anda mengembalikan beberapa objek ViewModel dengan koleksi terkait di dalamnya, tetapi koleksi tersebut tidak pernah digunakan (atau hanya digunakan sebagian). IQueryablememungkinkan Anda untuk menghindari biaya pengambilan catatan yang tidak digunakan.
Robert Harvey
3
Saya mengerti semua itu, hanya saja saya dibakar oleh orang-orang mengembalikan IQueryables di semua tempat. Dan kemudian sesuatu yang lebih jauh dari rantai menambahkan beberapa termasuk atau hal-hal lain yang dibuat untuk permintaan yang sangat buruk (dari perspektif kinerja DB). Dan itu adalah bug yang menyenangkan untuk dilacak. Karena itu, saya memiliki kesempatan untuk memikirkan apakah mengembalikan IQueryable adalah ide yang bagus. Dan saya tidak pernah bisa memikirkan waktu di mana itu bernilai masalah pemeliharaan. (lanjutan)
Becuzz
4
@RobertHarvey apa sebenarnya poin dari lapisan repositori jika mengembalikan IQueryable ke klien? Anda pada dasarnya memberi klien opsi untuk menulis kueri - tentu saja itu bukan kueri sql tapi tetap saja itu kueri (hanya ditulis menggunakan C #) dan akan ada di semua tempat. Jika repositori mengembalikan IQueryable maka Anda mungkin juga membuang repositori.
CodingYoshi
8
@ RobertTarvey Saya tidak setuju dengan tidak membuang DbContext dan tidak setuju dengan artikel yang dimaksud. Seluruh ide adalah untuk kode terhadap antarmuka dan antarmuka memberitahu saya itu IDisposable. Saya tidak akan menulis kode saya berdasarkan pada cara kerja dari bagaimana tim EF telah mengimplementasikan DbContext atau mengejar para devs di tim itu - mereka dapat mengubahnya kapan saja mereka mau. Saya juga tidak akan bertanya pada diri sendiri atau pengembang lain untuk mulai menggali bagian dalam setiap kelas untuk melihat apakah IDisposable benar-benar bermanfaat. Saya telah bekerja terlalu keras untuk mendapatkan devs di tim saya untuk membuang hanya untuk meminta mereka tidak selalu.
CodingYoshi
-3

Idealnya konteks harus diinisialisasi dan diakhiri untuk satu transaksi. Dalam kasus Anda konteksnya harus dipakai di Business Logic dan diteruskan ke Repositori untuk membaca / menulis data.

Gopinath
sumber
2
Ya, karena logika bisnis lebih dapat dipertahankan bila digabungkan secara erat dengan akses data ... :(
TheCatWhisperer
-3

Jika Anda memanggil DbContext pada setiap metode dalam aplikasi Anda, Anda akan mengalami kebocoran memori. Gunakan satu instance dari DbContext. Lihat komentar pada contoh di bawah ini:

public bool IsInStock(int _ProductId)
{
  var result = false;

  try
  {
    using (var dataService = new StoreDbDataService()) // NB: This line on each method will eventually cause memory leak.
    {
      result = dataService.IsInStock(_ProductId);
    }
  }
  catch (Exception ex)
  {
    Log.LogException(ex);
  }

  return result;
}
Joseph Majase Sithole
sumber
1
Bisakah Anda menjelaskan mengapa memanggil DbContext akan menyebabkan kebocoran memori? Komentar di sumber tidak membantu saya memahaminya. Saya akan berasumsi bahwa blok penggunaan akan menyebabkan Buang dipanggil pada StoreDBDataService yang pada akhirnya membersihkan semua sumber daya yang dialokasikan, bukan?
Kasper van den Berg
Ini pada dasarnya adalah klip "izin" Ron Swanson tetapi dalam kode.
Dagrooms