Banyak yang telah dikatakan sebelumnya, tetapi kembali ke akarnya, dengan cara yang lebih teknis:
IEnumerable
adalah kumpulan objek dalam memori yang dapat Anda hitung - urutan dalam memori yang memungkinkan untuk foreach
diulang (membuatnya mudah untuk dilakukan dalam loop, meskipun Anda hanya dapat menggunakannya IEnumerator
). Mereka tinggal di memori apa adanya.
IQueryable
adalah pohon ekspresi yang akan diterjemahkan ke sesuatu yang lain di beberapa titik dengan kemampuan untuk menghitung hasil akhir . Saya kira inilah yang membingungkan kebanyakan orang.
Mereka jelas memiliki konotasi yang berbeda.
IQueryable
mewakili pohon ekspresi (permintaan, sederhana) yang akan diterjemahkan ke sesuatu yang lain oleh penyedia permintaan yang mendasari segera setelah rilis API disebut, seperti fungsi agregat LINQ (Jumlah, Hitungan, dll.) atau Daftar [Array, Kamus,. ..] Dan IQueryable
objek juga diimplementasikan IEnumerable
, IEnumerable<T>
sehingga jika mereka merepresentasikan kueri , hasil dari kueri itu bisa diulang. Itu berarti IQueryable tidak harus menjadi pertanyaan saja. Istilah yang tepat adalah mereka pohon ekspresi .
Sekarang bagaimana ekspresi itu dieksekusi dan apa yang mereka berubah adalah semua yang disebut penyedia kueri (eksekutor ekspresi kita dapat memikirkannya).
Di dunia Entity Framework (yaitu penyedia sumber data yang mendasari mistis, atau penyedia kueri) IQueryable
diterjemahkan ke dalam kueri T-SQL asli . Nhibernate
melakukan hal serupa dengan mereka. Anda dapat menulis sendiri mengikuti konsep yang dijelaskan dengan baik di LINQ: Membangun tautan Penyedia IQueryable , misalnya, dan Anda mungkin ingin memiliki API kueri khusus untuk layanan penyedia toko produk Anda.
Jadi pada dasarnya, IQueryable
objek sedang dibangun jauh sampai kita secara eksplisit melepaskannya dan memberitahu sistem untuk menulis ulang mereka ke dalam SQL atau apa pun dan mengirimkan rantai eksekusi untuk diproses selanjutnya.
Seolah-olah untuk menunda eksekusi, ini adalah LINQ
fitur untuk menahan skema pohon ekspresi di memori dan mengirimkannya ke eksekusi hanya berdasarkan permintaan, setiap kali API tertentu dipanggil terhadap urutan (Hitungan yang sama, Daftar, dll.).
Penggunaan keduanya sangat tergantung pada tugas yang Anda hadapi untuk kasus tertentu. Untuk pola repositori terkenal saya pribadi memilih untuk kembali IList
, yaitu IEnumerable
lebih dari Daftar (pengindeks dan sejenisnya). Jadi ini adalah saran saya untuk menggunakan IQueryable
hanya di dalam repositori dan IEnumerable di tempat lain dalam kode. Tidak mengatakan tentang kekhawatiran yang dapat diuji yang IQueryable
rusak dan merusak prinsip pemisahan kekhawatiran . Jika Anda mengembalikan ekspresi dari dalam repositori, konsumen dapat bermain dengan lapisan kegigihan seperti yang mereka inginkan.
Sedikit tambahan ke kekacauan :) (dari diskusi di komentar)) Tidak satu pun dari mereka adalah objek dalam memori karena mereka bukan tipe nyata per se, mereka adalah penanda jenis - jika Anda ingin pergi sedalam itu. Tetapi masuk akal (dan itulah sebabnya bahkan MSDN mengatakannya seperti ini) untuk memikirkan IEnumerables sebagai koleksi dalam memori sedangkan IQueryables sebagai pohon ekspresi. Intinya adalah bahwa antarmuka IQueryable mewarisi antarmuka IEnumerable sehingga jika itu merupakan permintaan, hasil dari permintaan itu dapat disebutkan. Pencacahan menyebabkan pohon ekspresi yang terkait dengan objek IQueryable dieksekusi. Jadi, sebenarnya, Anda tidak dapat benar-benar memanggil anggota IEnumerable tanpa memiliki objek di memori. Ini akan masuk ke sana jika Anda melakukannya, jika tidak kosong. IQueryables hanyalah pertanyaan, bukan data.