Seluruh operator sudah kita lewati; sekarang tinggal mengubahnya menjadi kebiasaan. Kueri LINQ yang baik mudah dibaca, mengeksekusi secukupnya, dan tidak mengejutkan pengelolanya. Contoh terpadu berikut merangkai enam praktik utama section ini dalam satu pipeline.

Daftar Praktik Terbaik #

  1. Saring lebih dulu: letakkan Where sebelum operator lain agar elemen yang diproses semakin sedikit.
  2. Urutkan dengan kunci eksplisit sebelum Take atau Skip agar hasilnya deterministik.
  3. Materialisasi sekali dengan ToList bila hasil kueri dipakai berulang.
  4. Gunakan FirstOrDefault atau SingleOrDefault bila hasil kosong adalah kondisi yang wajar.
  5. Konsisten memilih satu gaya sintaks untuk satu kueri.
  6. Jangan menaruh kueri di dalam loop; bangun kuerinya sekali di luar loop.

Contoh Terpadu #

csharp
record Transaksi(int Id, int PelangganId, int Total);

List<Transaksi> transaksi = new()
{
    new Transaksi(101, 2, 85000),
    new Transaksi(102, 1, 120000),
    new Transaksi(103, 2, 45000),
    new Transaksi(104, 3, 60000)
};

var laporan = transaksi
    .Where(t => t.Total > 50000)
    .OrderByDescending(t => t.Total)
    .Take(2)
    .Select(t => new { t.Id, t.Total });

foreach (var baris in laporan)
{
    Console.WriteLine($"#{baris.Id}: {baris.Total}");
}

Output yang Dihasilkan:

text
#102: 120000
#101: 85000

Mari kita bedah baris demi baris:

  1. .Where(t => t.Total > 50000): penyaringan paling ketat diletakkan paling awal, sehingga tiga transaksi tersisa.
  2. .OrderByDescending(t => t.Total): urutan eksplisit memastikan dua transaksi teratas selalu sama.
  3. .Take(2): pembatasan jumlah dilakukan setelah urutan ditata.
  4. .Select(t => new { t.Id, t.Total }): projection terakhir memangkas bentuk hasil menjadi dua field yang benar-benar diperlukan.
  5. keterbacaan: setiap baris menyatakan satu langkah, sehingga maksud pipeline terbaca dari atas ke bawah tanpa komentar tambahan.

Dengan enam kebiasaan di atas, kueri kita tetap benar saat data bertambah besar dan tetap nyaman ditinjau saat kebutuhan berubah. Keenamnya berlaku untuk LINQ to Objects maupun provider database; poin terakhir justru lebih krusial pada EF Core karena kueri di dalam loop berarti satu perjalanan ke database untuk setiap elemen. Satu pola yang masih sering luput adalah kueri yang dipakai dua tempat: bila laporan di atas diiterasi sekali lagi, seluruh pipeline berjalan ulang, sehingga materialisasi menjadi pilihan yang tepat. Section LINQ selesai di sini; bab-bab sebelumnya dapat dijadikan rujukan cepat per operator.