C# İle Veritabanı Kayıt Arama İşlemi Nasıl Yapılır?

C# İle Veritabanı Kayıt Arama İşlemi Nasıl Yapılır?
C# İle Veritabanı Kayıt Arama İşlemi Nasıl Yapılır?

Yazılım geliştirme süreçlerinde en sık karşılaşılan ve kullanıcı deneyimini doğrudan etkileyen işlemlerden biri veri listeleme ve filtrelemedir. Modern uygulamalarda, kullanıcıların binlerce hatta milyonlarca veri arasından aradıkları bilgiye hızlıca ulaşabilmesi kritik bir öneme sahiptir. Bu rehberimizde, C# İle Veritabanı Kayıt Arama İşlemi Nasıl Yapılır? sorusunun yanıtını hem geleneksel ADO.NET yöntemleriyle hem de modern Entity Framework Core (EF Core) kütüphanesiyle adım adım inceleyeceğiz.

Bu makale, orta ve ileri düzey C# geliştiricileri ile kurumsal projelerde güvenli ve performanslı arama mekanizmaları kurmak isteyen yazılımcılar için hazırlanmıştır. Rehber boyunca yazacağımız kodlar, 2026 yılı standartlarına uygun, asenkron (async/await) yapıda, bellek dostu ve SQL Injection gibi siber güvenlik açıklarına karşı tamamen korunaklı olacaktır.

Eğitim boyunca SQL Server veritabanı üzerinde bir "Products" (Ürünler) tablosu kullanacağız. Bu tablo üzerinden tekil arama, metin tabanlı kısmi arama (LIKE sorguları), çoklu kriterlere göre dinamik filtreleme ve sayfalama (pagination) gibi gelişmiş teknikleri pratik örneklerle öğreneceksiniz.

Ön Hazırlık ve Gereksinimler

Uygulama kodlarına geçmeden önce geliştirme ortamımızın hazır olduğundan emin olmalıyız. Bu eğitimdeki örnekleri kendi bilgisayarınızda çalıştırmak için aşağıdaki bileşenlerin kurulu olması gerekmektedir:

  • .NET 8.0 SDK veya .NET 9.0 SDK: Modern C# özelliklerini kullanabilmek için güncel .NET çalışma zamanı.
  • IDE: Visual Studio 2022 (Sürüm 17.8 ve üzeri) veya JetBrains Rider.
  • Veritabanı: Microsoft SQL Server (LocalDB veya Express sürümü yeterlidir).
  • NuGet Paketleri: Projemize dahil etmemiz gereken Microsoft.Data.SqlClient ve Microsoft.EntityFrameworkCore.SqlServer kütüphaneleri.

Arama işlemlerini gerçekleştireceğimiz örnek veritabanı tablomuzun SQL şeması şu şekildedir:

CREATE TABLE Products (
    Id INT PRIMARY KEY IDENTITY(1,1),
    Name NVARCHAR(150) NOT NULL,
    Category NVARCHAR(100) NOT NULL,
    Price DECIMAL(18,2) NOT NULL,
    Stock INT NOT NULL,
    IsActive BIT NOT NULL DEFAULT 1
);

Yukarıdaki SQL kodu, arama senaryolarımızda kullanacağımız ürün adı, kategorisi, fiyatı ve stok durumu gibi alanları içeren temel bir tablo oluşturur. Şimdi bu tabloya C# uygulamamız içerisinden nasıl erişeceğimizi ve arama yapacağımızı görelim.

ADO.NET ile Parametreli Kayıt Arama Nasıl Yapılır?

ADO.NET, .NET ekosisteminin en temel veritabanı erişim teknolojisidir. Entity Framework gibi ORM (Object-Relational Mapping) araçlarına kıyasla daha düşük seviyede çalışır ancak maksimum performans sunar. ADO.NET ile arama yaparken dikkat edilmesi gereken en kritik nokta, kullanıcıdan alınan girdilerin doğrudan SQL sorgusuna eklenmemesi, parametre olarak geçilmesidir.

Aşağıdaki örnek kod, kullanıcının girdiği bir arama kelimesini (örneğin ürün adı) SQL Server veritabanında güvenli bir şekilde aramak için ADO.NET teknolojisini kullanmaktadır:

using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Threading.Tasks;

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; }
}

public class DatabaseSearchService
{
    private readonly string _connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=ShopDb;Trusted_Connection=True;";

    public async Task SearchProductsByNameAsync(string searchTerm)
    {
        var products = new List();
        
        // SQL sorgusunda LIKE operatörü ile kısmi arama yapıyoruz.
        // SQL Injection önlemek için @SearchTerm parametresini tanımlıyoruz.
        string query = "SELECT Id, Name, Category, Price, Stock FROM Products WHERE Name LIKE @SearchTerm AND IsActive = 1";

        using (SqlConnection connection = new SqlConnection(_connectionString))
        {
            using (SqlCommand command = new SqlCommand(query, connection))
            {
                // SQL parametresini güvenli bir şekilde ekliyoruz.
                // % karakterleri, kelimenin başında veya sonunda eşleşme aramak içindir.
                command.Parameters.AddWithValue("@SearchTerm", $"%{searchTerm}%");

                await connection.OpenAsync();
                
                using (SqlDataReader reader = await command.ExecuteReaderAsync())
                {
                    while (await reader.ReadAsync())
                    {
                        products.Add(new Product
                        {
                            Id = reader.GetInt32(0),
                            Name = reader.GetString(1),
                            Category = reader.GetString(2),
                            Price = reader.GetDecimal(3),
                            Stock = reader.GetInt32(4)
                        });
                    }
                }
            }
        }

        return products;
    }
}

Yukarıdaki kod bloğunda, SqlConnection ve SqlCommand nesneleri using blokları içerisinde tanımlanmıştır. Bu sayede veritabanı bağlantısı ve kaynaklar, işlem bittiğinde otomatik olarak bellekten temizlenir (Dispose edilir). AddWithValue metodu kullanılarak SQL Injection saldırıları tamamen engellenmiştir.

Kritik Güvenlik Uyarısı: SQL sorgularını asla "SELECT * FROM Products WHERE Name LIKE '" + userInput + "'" şeklinde yaygın bir hata olan dize birleştirme (string concatenation) yöntemiyle yazmayın. Bu yöntem, kötü niyetli kullanıcıların veritabanınızı ele geçirmesine (SQL Injection) yol açar.

Entity Framework Core (EF Core) ile LINQ Kullanarak Kayıt Arama

Günümüz modern C# projelerinde ADO.NET yerine genellikle Entity Framework Core tercih edilmektedir. EF Core, veritabanı tablolarını C# sınıfları ile eşleştirerek SQL yazmadan sorgulama yapmamızı sağlar. EF Core ile arama işlemleri LINQ (Language Integrated Query) sorguları aracılığıyla gerçekleştirilir.

İlk olarak, veritabanı bağlamımızı (DbContext) ve ürün modelimizi tanımlayalım:

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public DbSet Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=ShopDb;Trusted_Connection=True;");
    }
}

DbContext sınıfımız hazır olduğuna göre, artık LINQ kullanarak veritabanında filtreleme ve arama işlemlerini gerçekleştirebiliriz. EF Core, yazdığımız LINQ sorgularını arka planda otomatik olarak parametreli SQL sorgularına dönüştürür.

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

public class ProductRepository
{
    private readonly AppDbContext _context;

    public ProductRepository()
    {
        _context = new AppDbContext();
    }

    public async Task SearchByCategoryAsync(string categoryName)
    {
        // EF Core, String.Contains metodunu SQL'deki LIKE '%deger%' ifadesine dönüştürür.
        // AsNoTracking() kullanımı, sadece okuma yapılan sorgularda performansı ciddi oranda artırır.
        return await _context.Products
            .AsNoTracking()
            .Where(p => p.Category.Contains(categoryName) && p.IsActive)
            .ToListAsync();
    }
}

Yukarıdaki örnek kodda kullanılan AsNoTracking() metodu, EF Core'un nesne takip (change tracking) mekanizmasını devre dışı bırakır. Sadece arama sonuçlarını listelediğimiz ve bu veriler üzerinde bir güncelleme yapmayacağımız için bu metot bellek tüketimini azaltır ve sorgu hızını optimize eder.

Çoklu Kriterlere Göre Dinamik Arama Adım Adım

Gerçek hayat senaryolarında kullanıcılar genellikle sadece tek bir alana göre arama yapmazlar. Gelişmiş bir e-ticaret veya ERP sisteminde; ürün adı, kategori, minimum fiyat ve maksimum fiyat gibi birden fazla filtrenin aynı anda uygulanabilmesi gerekir. Bu duruma "Dinamik Sorgulama" denir.

Aşağıdaki örnek kod, kullanıcının doldurduğu alanlara göre SQL sorgusunu çalışma zamanında (runtime) dinamik olarak nasıl inşa edeceğimizi göstermektedir:

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

public class SearchFilters
{
    public string? Name { get; set; }
    public string? Category { get; set; }
    public decimal? MinPrice { get; set; }
    public decimal? MaxPrice { get; set; }
}

public class DynamicSearchService
{
    private readonly AppDbContext _context;

    public DynamicSearchService()
    {
        _context = new AppDbContext();
    }

    public async Task GetFilteredProductsAsync(SearchFilters filters)
    {
        // Sorguyu henüz veritabanına göndermeden IQueryable olarak başlatıyoruz.
        IQueryable query = _context.Products.AsNoTracking();

        // Sadece aktif ürünleri getir
        query = query.Where(p => p.IsActive);

        // İsim filtresi doluysa sorguya ekle
        if (!string.IsNullOrWhiteSpace(filters.Name))
        {
            query = query.Where(p => p.Name.Contains(filters.Name));
        }

        // Kategori filtresi doluysa sorguya ekle
        if (!string.IsNullOrWhiteSpace(filters.Category))
        {
            query = query.Where(p => p.Category == filters.Category);
        }

        // Minimum fiyat filtresi doluysa sorguya ekle
        if (filters.MinPrice.HasValue)
        {
            query = query.Where(p => p.Price >= filters.MinPrice.Value);
        }

        // Maksimum fiyat filtresi doluysa sorguya ekle
        if (filters.MaxPrice.HasValue)
        {
            query = query.Where(p => p.Price  p.Name.Contains(searchTerm) && p.IsActive);

        // Toplam eşleşen kayıt sayısını alıyoruz (Arayüzde sayfa sayılarını göstermek için)
        int totalCount = await query.CountAsync();

        // Skip: Önceki sayfalardaki kayıtları atlar.
        // Take: Sadece istenen sayfa boyutu kadar kayıt getirir.
        var items = await query
            .OrderBy(p => p.Id) // Sayfalama yaparken sıralama (ORDER BY) zorunludur.
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();

        return new PagedResult
        {
            Items = items,
            TotalCount = totalCount,
            PageNumber = pageNumber,
            PageSize = pageSize
        };
    }
}

Bu yöntem sayesinde, veritabanında 1 milyon ürün olsa dahi, kullanıcı 2. sayfayı talep ettiğinde veritabanından sadece ilgili 10 veya 20 kayıt çekilir. Bu durum ağ trafiğini azaltır, RAM kullanımını minimuma indirir ve uygulamanızın yanıt süresini milisaniyeler seviyesine çeker.

Veritabanı Arama Yöntemlerinin Karşılaştırılması

Projelerinizde hangi arama yöntemini seçeceğinize karar verirken performans, geliştirme hızı ve güvenlik gibi kriterleri göz önünde bulundurmalısınız. Aşağıdaki tablo, yaygın kullanılan C# veritabanı arama yaklaşımlarını karşılaştırmaktadır:

Yöntem Geliştirme Hızı Performans Derecesi SQL Injection Koruması Bakım Kolaylığı
ADO.NET (Parametreli) Yavaş / Manuel Çok Yüksek Tam (Doğru kullanılırsa) Zor (Büyük projelerde)
Dapper (Mikro ORM) Orta Çok Yüksek Tam (Parametreli sorgu ile) Orta
EF Core (LINQ) Çok Hızlı Yüksek (AsNoTracking ile) Otomatik ve Tam Çok Kolay

Hata Yönetimi ve Güvenlik Önlemleri

Veritabanı işlemleri doğası gereği dış etkenlere bağlıdır. Ağ kesintileri, veritabanı sunucusunun çevrimdışı olması veya yanlış yapılandırılmış bağlantı dizgileri (connection string) uygulamanızın çalışma zamanında hata vermesine neden olabilir. Bu nedenle arama kodlarımızı her zaman hata yönetimi (exception handling) blokları ile sarmalamalıyız.

Aşağıdaki örnek kod, arama işlemi sırasında oluşabilecek olası hataları güvenli bir şekilde yakalayan ve loglayan profesyonel bir yapıyı göstermektedir:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

public class SecureSearchService
{
    private readonly AppDbContext _context;

    public SecureSearchService()
    {
        _context = new AppDbContext();
    }

    public async Task                
Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Yaşam kalitesini artıran hızlı ve etkili yöntemler üzerine içerik geliştiriyorum. Detaylara önem veren, çözüm odaklı rehberlerin öncüsüyüm.

Yorumlar (0)

Yorum Yaz