ICollection <T> Vs List <T> dalam Entity Framework

115

Saya hanya menonton beberapa webcast sebelum saya mulai mendesain beberapa aplikasi Entity Framework. Saya benar-benar tidak membaca dokumentasi sebanyak itu dan saya merasa saya menderita karenanya.

Saya telah menggunakan List<T>di kelas saya, dan itu berhasil dengan baik.

Sekarang saya telah membaca beberapa dokumentasi dan menyatakan bahwa saya seharusnya menggunakan ICollection<T>. Saya mengubahnya ke ini, dan itu bahkan tidak menyebabkan perubahan konteks model. Apakah ini karena keduanya List<T>dan ICollection<T>mewarisi IEnumerable<T>, dan itulah yang sebenarnya diperlukan untuk EF?

Namun, jika hal ini terjadi, mengapa tidak negara dokumentasi EF yang membutuhkan IEnumerable<T>bukan ICollection<T>?

Bagaimanapun, apakah ada kerugian dari apa yang telah saya lakukan, atau haruskah saya mengubahnya?

wil
sumber

Jawaban:

113

Entity Framework akan digunakan ICollection<T>karena perlu mendukung Addoperasi, yang bukan merupakan bagian dari IEnumerable<T>antarmuka.

Juga ingat bahwa Anda sedang menggunakan ICollection<T>, Anda hanya mengekspos sebagai List<T>implementasi. List<T>membawa bersama dengan itu IList<T>, ICollection<T>dan IEnumerable<T>.

Mengenai perubahan Anda, mengekspos melalui antarmuka adalah pilihan yang baik, meskipun List<T>berfungsi. Antarmuka mendefinisikan kontrak tetapi bukan implementasinya. Implementasinya bisa berubah. Dalam beberapa kasus, mungkin implementasinya bisa menjadi HashSet<T>, misalnya. (Omong-omong, ini adalah pola pikir yang dapat Anda gunakan untuk lebih dari sekadar Entity Framework. Praktik berorientasi objek yang baik adalah memprogram ke arah antarmuka, bukan implementasinya. Penerapan bisa dan akan berubah.)

Anthony Pegram
sumber
2
Jadi .... hanya bagi saya untuk memahami lebih jauh - List mewarisi IList, yang mewarisi ICollection, yang mewarisi IEnumerable?
wil
3
Ya, itulah rantainya. List<T>harus menerapkan masing-masing interface ( IList<T>, ICollection<T>, IEnumerable<T>) karena hirarki warisan. Untuk menyelesaikannya, IList<T>ambil juga non-generik IList, ICollectiondan IEnumerableantarmuka.
Anthony Pegram
Terima kasih ... Beberapa fitur Ixxx masih luput dari pemahaman saya! Anda telah memahami, bagaimanapun, satu hal terakhir yang mengganggu saya, jika Ixx yang lain mewarisi IEnumerable, bagaimana cara menambahkan ke IEnumerable jika Ienumerable hanya bisa dibaca? ... Jika terlalu rumit, jangan khawatir, ketika saya punya sedikit waktu, saya akan mencoba menyalakan reflektor!
wil
10
Operasi Linq normal tidak menambah atau mengubah sesuatu, mereka hanya memfilter, mengelompokkan, memproyeksikan, dll. Hanya maju, urutan hanya-baca yang diperlukan untuk mendukung operasi tersebut. Jika Anda memiliki penyedia Linq seperti Entity Framework yang menangani persistensi data, kemampuan untuk Menambahkan adalah manfaat penting yang memerlukan antarmuka yang lebih canggih, yang mengundang ICollection<T>ke pesta (dan antarmuka ini membawa serta IEnumerable<T>, jadi "normal "Operasi Linq masih berlaku).
Anthony Pegram
@AnthonyPegram: Saya rasa tidak benar untuk mengatakan bahwa ketiga antarmuka harus diimplementasikan. Karena IList <T> mewarisi ICollection <T> yang mewarisi IEnumerable <T>, List <T> cukup untuk mengimplementasikan IList <T> saja.
CJ7
51

Mereka memilih antarmuka yang mereka lakukan karena memberikan abstraksi yang dapat dipahami atas kueri ajaib yang dilakukan oleh Entity Framework saat Anda menggunakan Linq.

Inilah perbedaan antar antarmuka:

  • IEnumerable<T> bersifat hanya baca
  • Anda dapat menambah dan menghapus item ke file ICollection<T>
  • Anda dapat melakukan akses acak (menurut indeks) ke a List<T>

Dari semua itu, ICollectiondan IEnumerablepetakan dengan baik ke operasi database, karena membuat kueri dan menambahkan / menghapus entitas adalah hal-hal yang mungkin Anda lakukan di DB.

Akses acak menurut indeks juga tidak dipetakan, karena Anda harus memiliki hasil kueri yang ada untuk mengulang, atau setiap akses acak akan meminta database lagi. Juga, apa tujuan peta indeks? Nomor baris? Tidak banyak kueri nomor baris yang ingin Anda lakukan, dan itu sama sekali tidak berguna dalam membangun kueri yang lebih besar. Jadi mereka tidak mendukungnya.

ICollection<T> didukung, dan akan memungkinkan Anda untuk menanyakan dan mengubah data, jadi gunakan itu.

Alasan List<T>bekerja untuk memulainya adalah karena implementasi EF pada akhirnya mengembalikan satu pada akhirnya. Tapi itu di akhir rantai kueri Anda, bukan di awal. Jadi membuat properti Anda ICollection<T>akan membuatnya lebih jelas bahwa EF membuat sekumpulan SQL dan hanya mengembalikan a List<T>di bagian akhir, daripada melakukan kueri untuk setiap level Linq yang Anda gunakan.

Merlyn Morgan-Graham
sumber
8

ICollection berbeda dari IEnumerable karena Anda sebenarnya dapat menambahkan item ke koleksi, sedangkan dengan IEnumerable Anda tidak bisa. Jadi di kelas POCO Anda, misalnya, Anda ingin menggunakan ICollection jika Anda ingin mengizinkan koleksi ditambahkan. Jadikan ICollection virtual untuk mendapatkan keuntungan dari pemuatan lambat juga.

Ralph Lavelle
sumber
1
Saya ingin memahami - Anda dapat melakukan operasi yang sama (dan banyak lagi!) Dengan List <T>. Mengapa ICollection <T>? Mengapa tidak Daftar <T>? Terlihat lebih sederhana dan lebih bertenaga.
monstro
Daftar <T> Menerapkan ICollection dan IEnumerable. Lebih banyak operasi tetapi dengan itu datang lebih banyak overhead.
IronAces
4

Meskipun pertanyaan tersebut telah diposting bertahun-tahun yang lalu, itu masih berlaku ketika seseorang mencari skenario yang sama.

Ada artikel CodeProject [2015] terbaru yang menjelaskan perbedaan secara mendetail dan representasi grafis dengan kode sampel . Ini tidak difokuskan secara langsung di EF tetapi tetap berharap ini akan lebih membantu:

Daftar vs IEnumerable vs IQuerable vs ICollection vs IDictionary

BiLaL
sumber