Saya melihat beberapa masalah pada jawaban @gunny229 di atas, itulah sebabnya saya menulis postingan ini. Saya telah menyebutkan masalah tersebut di area komentar postingannya juga. Untuk memperbaiki postingan itu saya harus menulis ulang hampir seluruh postingan jadi saya berpikir untuk membuatnya sendiri. Saya tidak bermaksud menjawab pertanyaan OP secara keseluruhan tetapi saya ingin menunjukkan perbedaan antara IQueryable dan IEnumerable saat menggunakan LINQ ke SQL.
Saya membuat struktur berikut di DB (skrip DDL):
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Berikut adalah skrip penyisipan catatan (skrip DML):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
Sekarang tujuan saya adalah mendapatkan 2 catatan teratas dari tabel Employee
di database. Jadi, saya menambahkan item Model Data Entitas ADO.NET ke dalam aplikasi konsol saya yang menunjuk ke tabel Employee
di database saya dan mulai menulis kueri LINQ.
Kode untuk rute yang dapat dikueri:
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Ketika saya mulai menjalankan program ini, saya juga memulai sesi profiler SQL Query pada contoh SQL Server saya dan berikut adalah ringkasan eksekusinya:
- Jumlah total kueri yang diaktifkan: 1
- Teks kueri:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
Hanya saja IQueryable
cukup pintar untuk menerapkan klausa Top (2)
pada sisi server database itu sendiri sehingga hanya membawa 2 dari 5 catatan melalui kabel. Pemfilteran lebih lanjut dalam memori tidak diperlukan sama sekali di sisi komputer klien.
Kode untuk rute IEnumerable:
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
Ringkasan eksekusi dalam hal ini:
- Jumlah total kueri yang diaktifkan: 1
- Teks kueri yang diambil dalam profiler SQL:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Sekarang masalahnya adalah IEnumerable
membawa semua 5 catatan yang ada di tabel Salary
dan kemudian melakukan pemfilteran dalam memori di komputer klien untuk mendapatkan 2 catatan teratas. Jadi lebih banyak data (3 catatan tambahan dalam kasus ini) ditransfer melalui kabel jika tidak perlu.
person
RBT
schedule
26.04.2017