Apa gunanya IQueryable
dalam konteks LINQ?
Apakah digunakan untuk mengembangkan metode penyuluhan atau tujuan lain?
sumber
Apa gunanya IQueryable
dalam konteks LINQ?
Apakah digunakan untuk mengembangkan metode penyuluhan atau tujuan lain?
Jawaban Marc Gravell sangat lengkap, tetapi saya pikir saya akan menambahkan sesuatu tentang ini dari sudut pandang pengguna, juga ...
Perbedaan utama, dari perspektif pengguna, adalah bahwa, ketika Anda menggunakan IQueryable<T>
(dengan penyedia yang mendukung hal-hal dengan benar), Anda dapat menghemat banyak sumber daya.
Misalnya, jika Anda bekerja melawan basis data jauh, dengan banyak sistem ORM, Anda memiliki opsi untuk mengambil data dari tabel dengan dua cara, yang mengembalikan IEnumerable<T>
, dan yang mengembalikan IQueryable<T>
. Misalnya, Anda memiliki tabel Produk, dan Anda ingin mendapatkan semua produk yang biayanya> $ 25.
Jika kamu melakukan:
IEnumerable<Product> products = myORM.GetProducts();
var productsOver25 = products.Where(p => p.Cost >= 25.00);
Apa yang terjadi di sini, adalah database memuat semua produk, dan meneruskannya ke program Anda. Program Anda kemudian menyaring data. Intinya, database melakukan SELECT * FROM Products
, dan mengembalikan setiap produk kepada Anda.
Dengan IQueryable<T>
penyedia yang tepat , di sisi lain, Anda dapat melakukan:
IQueryable<Product> products = myORM.GetQueryableProducts();
var productsOver25 = products.Where(p => p.Cost >= 25.00);
Kode tersebut terlihat sama, tetapi perbedaannya di sini adalah SQL yang dieksekusi SELECT * FROM Products WHERE Cost >= 25
.
Dari POV Anda sebagai pengembang, ini terlihat sama. Namun, dari sudut pandang kinerja, Anda hanya dapat mengembalikan 2 catatan di seluruh jaringan, bukan 20.000 ....
IQueryable<Product>
- akan spesifik untuk ORM atau repositori Anda, dll.foreach
, atau panggilanToList()
), Anda tidak benar-benar menekan DB.Pada dasarnya pekerjaannya sangat mirip dengan
IEnumerable<T>
- untuk mewakili sumber data yang dapat ditanyakan - perbedaannya adalah bahwa berbagai metode LINQ (onQueryable
) dapat lebih spesifik, untuk membangun kueri menggunakanExpression
pohon daripada delegasi (yang digunakan adalah apaEnumerable
).Pohon ekspresi dapat diperiksa oleh penyedia LINQ yang Anda pilih dan berubah menjadi permintaan yang sebenarnya - meskipun itu sendiri merupakan seni hitam.
Ini benar-benar ke bawah
ElementType
,Expression
danProvider
- tetapi dalam kenyataannya Anda jarang perlu peduli tentang ini sebagai pengguna . Hanya pelaksana LINQ yang perlu mengetahui detail berdarah.Komentar ulang; Saya tidak yakin apa yang Anda inginkan dengan contoh, tetapi pertimbangkan LINQ-to-SQL; objek utama di sini adalah
DataContext
, yang mewakili pembungkus basis data kami. Ini biasanya memiliki properti per tabel (misalnya,Customers
), dan tabel mengimplementasikanIQueryable<Customer>
. Tapi kami tidak menggunakan itu secara langsung; mempertimbangkan:ini menjadi (oleh kompiler C #):
yang lagi ditafsirkan (oleh kompiler C #) sebagai:
Yang penting, metode statis pada
Queryable
pohon ekspresi mengambil, yang - daripada IL biasa, bisa dikompilasi ke model objek. Misalnya - hanya melihat "Di mana", ini memberi kita sesuatu yang sebanding dengan:Bukankah kompiler melakukan banyak hal untuk kita? Model objek ini dapat dirobek, diperiksa apa artinya, dan disatukan kembali oleh generator TSQL - memberikan sesuatu seperti:
(string mungkin berakhir sebagai parameter; Saya tidak ingat)
Semua ini tidak akan mungkin terjadi jika kami baru saja menggunakan delegasi. Dan ini adalah titik
Queryable
/IQueryable<T>
: ia menyediakan titik masuk untuk menggunakan pohon ekspresi.Semua ini sangat kompleks, sehingga merupakan pekerjaan yang bagus sehingga kompiler membuatnya bagus dan mudah bagi kami.
Untuk informasi lebih lanjut, lihat " C # in Depth " atau " LINQ in Action ", yang keduanya menyediakan cakupan topik-topik ini.
sumber
Meskipun Reed Copsey dan Marc Gravell sudah menjelaskan tentang
IQueryable
(dan jugaIEnumerable
) cukup, saya ingin menambahkan lebih banyak di sini dengan memberikan contoh kecilIQueryable
danIEnumerable
karena banyak pengguna memintanyaContoh : Saya telah membuat dua tabel dalam database
Kunci Utama (
PersonId
) dari tabelEmployee
juga merupakan kunci forgein (personid
) dari tabelPerson
Selanjutnya saya menambahkan model entitas ado.net dalam aplikasi saya dan membuat kelas layanan di bawah itu
mereka berisi LINQ yang sama. Itu disebut
program.cs
seperti yang didefinisikan di bawah iniOutputnya sama untuk keduanya
Jadi pertanyaannya adalah apa / di mana bedanya? Sepertinya tidak ada bedanya kan? Betulkah!!
Mari kita lihat query sql yang dihasilkan dan dieksekusi oleh entitas framwork 5 selama periode ini
Bagian eksekusi IQueryable
Bagian eksekusi IEnumerable
Skrip umum untuk kedua bagian eksekusi
Jadi, Anda memiliki beberapa pertanyaan sekarang, izinkan saya menebaknya dan mencoba menjawabnya
Mengapa skrip yang berbeda dihasilkan untuk hasil yang sama?
Mari kita cari beberapa poin di sini,
semua pertanyaan memiliki satu bagian yang sama
WHERE [Extent1].[PersonId] IN (0,1,2,3)
Mengapa? Karena kedua fungsi
IQueryable<Employee> GetEmployeeAndPersonDetailIQueryable
danIEnumerable<Employee> GetEmployeeAndPersonDetailIEnumerable
dariSomeServiceClass
berisi satu baris umum dalam permintaan LINQwhere employeesToCollect.Contains(e.PersonId)
Daripada mengapa
AND (N'M' = [Extent1].[Gender])
bagian itu hilang diIEnumerable
bagian eksekusi, sementara di kedua fungsi memanggil kami menggunakanWhere(i => i.Gender == "M") in
program.cs`Apa yang dilakukan kerangka entitas ketika suatu
IQueryable
metode dipanggil, ia mengambil pernyataan linq yang ditulis di dalam metode dan mencoba untuk mencari tahu apakah lebih banyak ekspresi linq didefinisikan pada resultset, itu kemudian mengumpulkan semua permintaan linq didefinisikan sampai hasilnya perlu mengambil dan membangun sql yang lebih tepat permintaan untuk dieksekusi.Ini memberikan banyak manfaat seperti,
seperti di sini dalam contoh sql server kembali ke aplikasi hanya dua baris setelah eksekusi IQueryable` tetapi mengembalikan TIGA baris untuk permintaan IEnumerable mengapa?
Dalam hal
IEnumerable
metode, kerangka kerja mengambil pernyataan LINQ yang ditulis di dalam metode dan membangun kueri sql ketika hasilnya perlu diambil. itu tidak termasuk bagian rest linq untuk membangun kueri sql. Seperti di sini, tidak ada penyaringan yang dilakukan di sql server pada kolomgender
.Tetapi hasilnya sama? Karena 'IEnumerable memfilter hasil lebih lanjut di level aplikasi setelah mengambil hasil dari sql server
JADI, apa yang harus seseorang pilih? Saya pribadi lebih suka mendefinisikan hasil fungsi
IQueryable<T>
karena ada banyak manfaatnyaIEnumerable
seperti, Anda bisa bergabung dengan dua atau lebih fungsi IQueryable, yang menghasilkan skrip yang lebih spesifik ke server sql.Di sini, dalam contoh Anda dapat melihat
IQueryable Query(IQueryableQuery2)
skrip menghasilkan lebih spesifik daripadaIEnumerable query(IEnumerableQuery2)
yang jauh lebih dapat diterima menurut saya.sumber
Hal ini memungkinkan untuk pertanyaan lebih lanjut di telepon. Jika ini melampaui batas layanan, maka pengguna objek yang IQueryable ini akan diizinkan untuk berbuat lebih banyak dengannya.
Misalnya jika Anda menggunakan lazy loading dengan nhibernate, ini dapat mengakibatkan grafik dimuat ketika / jika diperlukan.
sumber