C# İle Lınq Sorguları Kullanarak Veri Filtreleme İşlemi Nasıl Yapılır?

C# İle Lınq Sorguları Kullanarak Veri Filtreleme İşlemi Nasıl Yapılır?
C# İle Lınq Sorguları Kullanarak Veri Filtreleme İşlemi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu makaledeki örnekleri uygulamak için bilgisayarınızda .NET 8 veya .NET 9 SDK yüklü olmalıdır. Geliştirme ortamı olarak Visual Studio 2022 veya VS Code kullanabilirsiniz. LINQ yeteneklerini kullanabilmek için projenizin en üst kısmına using System.Linq; namespace'ini eklemeyi unutmayın.

  • .NET 8+ SDK
  • Visual Studio 2022 veya güncel bir IDE
  • Temel C# koleksiyon bilgisi (List, IEnumerable)

LINQ Where Operatörü ile Temel Filtreleme

LINQ'in en temel filtreleme aracı Where metodudur. Bu metod, bir koşul (predicate) alır ve bu koşulu sağlayan tüm öğeleri döndürür. Aşağıdaki örnekte, bir tam sayı listesinden sadece çift sayıları filtreliyoruz.

using System;
using System.Collections.Generic;
using System.Linq;

var sayilar = new List { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var ciftSayilar = sayilar.Where(s => s % 2 == 0).ToList();

ciftSayilar.ForEach(s => Console.WriteLine(s));

Burada s => s % 2 == 0 ifadesi bir lambda fonksiyonudur. Her bir elemanı s değişkenine atar ve 2'ye bölümünden kalan 0 olanları seçer. ToList() metodu, sorguyu hemen çalıştırarak sonucu bir liste olarak belleğe alır.

Nesne Koleksiyonlarında Filtreleme Yapmak

Gerçek dünya projelerinde genellikle basit tipler yerine karmaşık nesnelerle çalışırız. Bir "Ürün" sınıfı üzerinden fiyatı belirli bir değerin üzerinde olan ürünleri filtreleyelim.

public class Urun {
    public string Ad { get; set; }
    public decimal Fiyat { get; set; }
}

var urunler = new List {
    new Urun { Ad = "Laptop", Fiyat = 25000 },
    new Urun { Ad = "Mouse", Fiyat = 500 },
    new Urun { Ad = "Klavye", Fiyat = 1200 }
};

var pahaliUrunler = urunler.Where(u => u.Fiyat > 1000).ToList();

Bu kodda, nesne özelliklerine (property) erişerek filtreleme yaptık. u değişkeni Urun tipindeki her bir nesneyi temsil eder ve u.Fiyat üzerinden mantıksal sorgulamamızı gerçekleştirdik.

Çoklu Kriter ile Filtreleme (And/Or)

Bazen birden fazla koşulu aynı anda kontrol etmeniz gerekir. C# LINQ sorgularında && (ve) ve || (veya) operatörlerini kullanarak karmaşık filtreleme mantıkları kurabilirsiniz.

// Fiyatı 1000'den büyük VE adı 'L' ile başlayan ürünler
var filtrelenmis = urunler.Where(u => u.Fiyat > 1000 && u.Ad.StartsWith("L")).ToList();

Bu yöntem, veritabanı sorgularında (Entity Framework kullanıldığında) SQL'deki WHERE cümlesine karşılık gelir. Kodun okunabilirliğini artırmak için karmaşık filtreleri ayrı metotlara taşıyabilirsiniz.

Güvenlik Uyarısı: Kullanıcıdan gelen verileri doğrudan LINQ sorgularına dahil etmeyin. Eğer Entity Framework kullanıyorsanız, parametreli sorgular (parameterized queries) otomatik olarak oluşturulur. Ancak ham SQL sorgularında SQL Injection riskine karşı her zaman dikkatli olunmalıdır.

LINQ Yöntem Sözdizimi (Method Syntax) vs Sorgu Sözdizimi (Query Syntax)

LINQ sorgularını yazmanın iki yolu vardır. Yöntem sözdizimi zincirleme metotlar kullanırken, sorgu sözdizimi SQL benzeri bir yapı sunar.

// Sorgu Sözdizimi (Query Syntax)
var sorgu = from u in urunler
            where u.Fiyat > 1000
            select u;

var sonuc = sorgu.ToList();

Aşağıdaki tablo, bu iki yaklaşımın karşılaştırmasını sunar:

Özellik Yöntem Sözdizimi (Method) Sorgu Sözdizimi (Query)
Okunabilirlik Zincirleme yapıda daha karmaşık SQL'e yakın, daha anlaşılır
Esneklik Daha fazla operatör desteği Sınırlı (Join/Group işlemleri için iyi)
Kullanım Genel kullanım için standart Karmaşık veritabanı joinleri için tercih edilir

Yaygın Hatalar ve Debug İpuçları

LINQ kullanırken en sık karşılaşılan hata NullReferenceException hatasıdır. Filtreleme yapacağınız koleksiyonun null olup olmadığını kontrol etmek, uygulamanızın çökmesini engeller.

// Hatalı veya boş liste kontrolü
var liste = GetUrunler(); // null dönebilir
var sonuc = liste?.Where(u => u.Fiyat > 500).ToList() ?? new List();

?. (null-conditional) operatörü ve ?? (null-coalescing) operatörü, LINQ sorgularında güvenli veri işleme için vazgeçilmezdir.

Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce birim testleri (unit tests) yazmalı ve veri güvenliği standartlarınıza uygunluğunu doğrulamalısınız.

Sıkça Sorulan Sorular

LINQ sorguları performansı nasıl etkiler?

LINQ, özellikle büyük veri setlerinde bellekte (in-memory) işlem yaparken biraz ek yük getirebilir. Ancak Entity Framework gibi kütüphanelerle kullanıldığında, LINQ sorguları SQL'e çevrilerek veritabanı seviyesinde optimize edilir.

Deferred Execution (Gecikmeli Yürütme) nedir?

LINQ sorguları, ToList() veya ToArray() gibi bir metot çağrılana kadar çalışmaz. Bu, sorgunun veritabanına veya koleksiyona ne zaman gideceğini kontrol etmenizi sağlar.

Where metodu ile FirstOrDefault farkı nedir?

Where bir koleksiyon döndürür; FirstOrDefault ise koşulu sağlayan ilk öğeyi döndürür, koşula uyan öğe yoksa null döner.

LINQ ile verileri nasıl sıralarım?

Filtreleme işleminden sonra OrderBy(u => u.Fiyat) veya OrderByDescending(u => u.Fiyat) metotlarını zincirleme olarak ekleyebilirsiniz.

LINQ sorgularında case-insensitive (büyük/küçük harf duyarsız) arama nasıl yapılır?

Where(u => u.Ad.Equals("laptop", StringComparison.OrdinalIgnoreCase)) şeklinde bir karşılaştırma kullanarak harf duyarlılığını kaldırabilirsiniz.

LINQ Sorgularında İleri Düzey Filtreleme Teknikleri: PredicateBuilder Kullanımı

Standart LINQ sorguları, çalışma zamanında (runtime) dinamik olarak oluşturulması gereken filtreleme senaryolarında kısıtlı kalabilir. Örneğin, bir arama ekranında kullanıcının seçtiği filtrelerin (kategori, fiyat aralığı, stok durumu) değişkenlik gösterdiği durumlarda, her kombinasyon için ayrı bir Where bloğu yazmak verimsizdir. Bu noktada PredicateBuilder gibi yardımcı kütüphaneler veya Expression Tree yapıları devreye girer.

Dinamik filtreleme oluşturmak için System.Linq.Expressions namespace'i altındaki yapıları kullanarak sorgunuzu çalışma anında birleştirebilirsiniz:

using System.Linq.Expressions;

public static Expression True() { return f => true; }

// Kullanım örneği:
var predicate = True();
if (!string.IsNullOrEmpty(aramaTerimi)) {
    predicate = predicate.And(u => u.Ad.Contains(aramaTerimi));
}
if (minFiyat > 0) {
    predicate = predicate.And(u => u.Fiyat >= minFiyat);
}

var filtrelenmisListe = urunler.AsQueryable().Where(predicate).ToList();

LINQ Sorgularında Performans Optimizasyonu ve İndeksleme

LINQ ile büyük veri setleri üzerinde filtreleme yaparken, sorgunun veritabanı seviyesinde mi yoksa bellek (in-memory) üzerinde mi çalıştığı kritik bir önem taşır. IEnumerable yerine IQueryable kullanmak, filtreleme işleminin veritabanına bir SQL sorgusu olarak gönderilmesini sağlar. Bu, tüm veriyi belleğe çekmek yerine sadece filtrelenmiş sonuçların getirilmesini sağlayarak bellek tüketimini ciddi oranda düşürür.

Performansı artırmak için dikkat etmeniz gereken temel noktalar şunlardır:

  • Sorgu Öteleme: Gereksiz ToList() veya ToArray() çağrılarından kaçının. Bu metotlar sorguyu hemen çalıştırır ve veriyi belleğe yükler.
  • Projection (Seçim): Sadece ihtiyacınız olan kolonları çekin. Select(u => new { u.Ad, u.Fiyat }) kullanarak gereksiz veri transferini engelleyin.
  • Veritabanı İndeksleri: Where koşulunda kullandığınız alanların (örneğin UrunKategoriId) veritabanı tarafında indekslendiğinden emin olun. İndekslenmemiş alanlarda yapılan filtrelemeler, veri miktarı arttıkça sorgu süresini logaritmik olarak uzatır.

Aşağıdaki örnekte, veriyi belleğe almadan sadece gerekli alanların nasıl seçileceği gösterilmiştir:

// Verimsiz: Tüm nesneyi çeker
var tumVeri = context.Urunler.Where(u => u.Stok > 0).ToList();

// Verimli: Sadece gerekli kolonları çeker ve veritabanı tarafında filtreler
var optimizeVeri = context.Urunler
    .Where(u => u.Stok > 0)
    .Select(u => new UrunDTO { 
        Ad = u.Ad, 
        Fiyat = u.Fiyat 
    })
    .ToList();
Not: Büyük ölçekli uygulamalarda Contains veya StartsWith gibi metotlar, veritabanı tarafında LIKE operatörüne dönüşür. Bu operatörlerin başında joker karakter (%) kullanılması, veritabanı indekslerinin çalışmamasına (Index Scan) neden olabilir.

Sonuç

C# ile LINQ kullanarak veri filtreleme, modern yazılım geliştirmenin temel bir becerisidir. Bu makalede, Where operatöründen başlayarak nesne koleksiyonlarında filtreleme yapmayı, çoklu kriterleri yönetmeyi ve yöntem sözdizimi ile sorgu sözdizimi arasındaki farkları öğrendiniz. Bir sonraki adım olarak, LINQ ile Join işlemlerini inceleyerek ilişkisel veriler üzerinde nasıl sorgulama yapabileceğinizi keşfedebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Sürdürülebilir yaşam ve pratik ev yönetimi üzerine içerik stratejileri geliştiriyorum. Yalın anlatımı ve uygulanabilirliği ön planda tutan bir yazı dilim var.

Yorumlar (0)

Yorum Yaz