Apa perbedaan antara IQueryable dan IEnumerable

Jawaban:

186

IEnumerable<T>mewakili hanya kursor maju dari T. .NET 3.5 menambahkan metode ekstensi yang mencakup LINQ standard query operatorssuka Wheredan First, dengan operator apa pun yang membutuhkan predikat atau fungsi anonim Func<T>.

IQueryable<T>mengimplementasikan operator kueri standar LINQ yang sama, tetapi menerima Expression<Func<T>>predikat dan fungsi anonim. Expression<T>adalah pohon ekspresi terkompilasi, versi rusak dari metode ("setengah dikompilasi" jika Anda mau) yang dapat diuraikan oleh penyedia kueri dan digunakan sesuai.

Sebagai contoh:

IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

Di blok pertama, x => x.Age > 18adalah metode anonim ( Func<Person, bool>), yang dapat dieksekusi seperti metode lainnya. Enumerable.Whereakan mengeksekusi metode sekali untuk setiap orang, yieldnilai-nilai yang metode dikembalikan true.

Di blok kedua, x => x.Age > 18adalah pohon ekspresi ( Expression<Func<Person, bool>>), yang dapat dianggap sebagai "adalah properti 'Umur'> 18".

Ini memungkinkan hal-hal seperti LINQ-to-SQL ada karena mereka dapat mengurai pohon ekspresi dan mengubahnya menjadi SQL yang setara. Dan karena penyedia tidak perlu mengeksekusi sampai IQueryabledisebutkan (itu mengimplementasikan IEnumerable<T>, setelah semua), ia dapat menggabungkan beberapa operator permintaan (dalam contoh di atas Wheredan FirstOrDefault) untuk membuat pilihan yang lebih cerdas tentang bagaimana menjalankan seluruh permintaan terhadap data yang mendasarinya sumber (seperti menggunakan SELECT TOP 1dalam SQL).

Lihat:

Richard Szalay
sumber
1
jawaban yang cukup singkat
ashveli
83

Dalam kehidupan nyata, jika Anda menggunakan ORM seperti LINQ-to-SQL

  • Jika Anda membuat IQueryable, maka kueri dapat dikonversi ke sql dan dijalankan di server database
  • Jika Anda membuat IEnumerable, maka semua baris akan ditarik ke dalam memori sebagai objek sebelum menjalankan kueri.

Dalam kedua kasus jika Anda tidak memanggil ToList()atau ToArray()kemudian permintaan akan dieksekusi setiap kali digunakan, jadi, katakanlah, Anda memiliki IQueryabledan Anda mengisi 4 kotak daftar dari itu, maka permintaan akan dijalankan terhadap database 4 kali.

Juga jika Anda memperluas kueri Anda:

q.Select(x.name = "a").ToList()

Kemudian dengan IQueryableSQL yang dihasilkan akan berisi where name = "a", tetapi dengan IEnumerablelebih banyak peran akan ditarik kembali dari database, maka x.name = "a"pemeriksaan akan dilakukan oleh .NET.

Ian Ringrose
sumber
"kueri dapat dikonversi ke sql": Saya tidak mendapatkan 'mungkin'. Juga, jika saya memiliki IEnumerable dan membuat 'rantai kompleks' maka (jelas) tidak seperti IQueryable, itu tidak akan diterjemahkan ke dalam query SQL 'dioptimalkan'. Hanya ingin mengkonfirmasi apa artinya ketika Anda mengatakan 'semua baris akan ditarik ke dalam memori'. Mari kita katakan bahwa saya memiliki dua klausa di mana, maka semua tupel entitas akan pertama-tama diambil ke dalam memori dan kemudian penyaringan 'dalam-memori' yang normal akan terjadi?
Vaibhav
36

"Perbedaan utama adalah bahwa metode ekstensi yang didefinisikan untuk mengambil objek Ekspresi IQueryable bukan objek Func, berarti delegasi yang diterimanya adalah pohon ekspresi bukan metode untuk memanggil. IEnumerable sangat bagus untuk bekerja dengan koleksi dalam memori, tetapi IQueryable memungkinkan untuk sumber data jarak jauh, seperti basis data atau layanan web "

Sumber: di sini

Gabe
sumber
19

IEnumerable IEnumerable paling cocok untuk bekerja dengan koleksi dalam memori. IEnumerable tidak bergerak di antara item, itu hanya meneruskan koleksi.

IQueryable IQueryable paling cocok untuk sumber data jarak jauh, seperti database atau layanan web. IQueryable adalah fitur yang sangat kuat yang memungkinkan berbagai skenario eksekusi yang ditangguhkan yang menarik (seperti permintaan halaman dan komposisi berdasarkan).

Jadi ketika Anda harus hanya mengulangi koleksi di dalam memori, gunakan IEnumerable, jika Anda perlu melakukan manipulasi dengan koleksi seperti Dataset dan sumber data lainnya, gunakan IQueryable

Talha
sumber
11

Perbedaan prinsipnya adalah bahwa IEnumerable akan menghitung semua elemennya setiap saat, sedangkan IQueryable akan menghitung elemen, atau bahkan melakukan hal-hal lain, berdasarkan permintaan. Kueri adalah Ekspresi (representasi data dari kode .Net), yang harus dijelajahi / ditafsirkan / dikompilasi oleh IQueryProvider untuk menghasilkan hasil.

Memiliki ekspresi permintaan memberikan dua keuntungan.

Keuntungan pertama adalah optimasi. Karena pengubah seperti 'Di mana' termasuk dalam ekspresi kueri, IQueryProvider dapat menerapkan optimasi yang tidak mungkin dilakukan. Alih-alih mengembalikan semua elemen lalu membuang sebagian besar dari mereka karena klausa 'Di mana', penyedia bisa menggunakan tabel hash untuk menemukan item dengan kunci yang diberikan.

Keuntungan kedua adalah fleksibilitas. Karena Ekspresi adalah struktur data yang dapat dieksplor, Anda dapat melakukan hal-hal seperti membuat serial permintaan dan mengirimkannya ke mesin jarak jauh (mis. Linq-to-sql).

Craig Gidney
sumber
1

IEnumerable pertama kali ditemukan di System.Collections Namespace sedangkan IQueryable ditemukan di System.Linq Namespace. Jika Anda menggunakan IEnumerable ketika meminta data dari koleksi di-memori seperti Daftar, koleksi Array dll. Dan ketika meminta data dari memori-out (seperti database jauh, layanan) koleksi sehingga Anda menggunakan IQueryable. Karena Sementara meng-query data dari database, IEnumerable menjalankan query pilih di sisi server, memuat data di-memori di sisi klien dan kemudian menyaring data. Karenanya bekerja lebih banyak dan menjadi lambat. Saat meminta data dari basis data, IQueryable menjalankan kueri pemilihan di sisi server dengan semua filter. Karenanya kurang bekerja dan menjadi cepat.

Nayeem Mansoori
sumber