C# İle Entity Framework Kullanarak Veri Sorgulama Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

EF Core ile çalışmaya başlamadan önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. 2026 yılı itibarıyla .NET 9 veya üzeri bir sürüm kullanmanız önerilir. Projenize gerekli kütüphaneleri eklemek için aşağıdaki adımları takip edin.

  • Visual Studio 2022 veya VS Code güncel sürümü.
  • Proje dosyanızda Microsoft.EntityFrameworkCore.SqlServer paketi.
  • Veritabanı bağlantı dizesini (connection string) tutan appsettings.json dosyası.

Paketleri yüklemek için terminalinize şu komutu yazabilirsiniz:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design

Bu paketler, Entity Framework'ün SQL Server ile haberleşmesini ve tasarım zamanı araçlarını projenize dahil edecektir.

DbContext Yapılandırması ve Veri Modeli

Veri sorgulama işlemlerine başlamadan önce, veritabanı ile uygulamanız arasındaki köprü olan DbContext sınıfını tanımlamanız gerekir. Bu sınıf, veritabanındaki tabloları C# sınıfları (Entity) olarak temsil eder.

public class UygulamaDbContext : DbContext
{
    public DbSet Urunler { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;");
    }
}

Yukarıdaki kod, Urunler tablosuna erişmemizi sağlayan bir köprü oluşturur. DbSet, veritabanındaki tablonun C# tarafındaki karşılığıdır.

LINQ ile Temel Veri Sorgulama Yöntemleri

Entity Framework, sorguları oluşturmak için LINQ kullanır. En temel sorgu yöntemi, tüm verileri veya belirli bir koşula uyan verileri çekmektir. Aşağıdaki örnek, veritabanındaki tüm ürünleri listelemeyi gösterir.

using (var context = new UygulamaDbContext())
{
    var tumUrunler = context.Urunler.ToList();
    foreach (var urun in tumUrunler)
    {
        Console.WriteLine($"{urun.Ad} - {urun.Fiyat} TL");
    }
}

ToList() metodu, sorguyu veritabanına gönderir ve sonuçları belleğe alır. Büyük veri setlerinde tüm veriyi çekmek yerine IQueryable yapısını koruyarak filtreleme yapmak performans açısından kritiktir.

Filtreleme, Sıralama ve Sayfalama

Gerçek dünya uygulamalarında genellikle tüm veriye değil, belirli kriterlere uyan verilere ihtiyaç duyarız. Where ile filtreleme, OrderBy ile sıralama ve Skip/Take ile sayfalama yapabilirsiniz.

var pahaliUrunler = context.Urunler
    .Where(u => u.Fiyat > 500)
    .OrderByDescending(u => u.Fiyat)
    .Skip(0)
    .Take(10)
    .ToList();

Bu sorgu, 500 TL üzerindeki ürünleri en pahalıdan en ucuza sıralar ve sadece ilk 10 tanesini getirir. Bu yöntem, veritabanı üzerindeki yükü ciddi oranda azaltır.

Performans İpuçları ve Sorgu Optimizasyonu

Veri sorgulama sırasında yapılan en yaygın hata, gereksiz verileri çekmektir. Select kullanarak sadece ihtiyacınız olan kolonları çekmek, bellek kullanımını optimize eder.

var urunIsimleri = context.Urunler
    .Where(u => u.StokAdedi > 0)
    .Select(u => new { u.Ad, u.Fiyat })
    .ToList();

Bu örnekte, tüm Urun nesnesini değil, sadece Ad ve Fiyat alanlarını içeren anonim bir nesne çekiyoruz. Bu, "Projection" (İzdüşüm) olarak adlandırılır.

Sorgulama Yöntemlerinin Karşılaştırması

Yöntem Avantaj Dezavantaj
LINQ Method Syntax Okunabilir, zincirleme kolay Karmaşık sorgularda zorlaşabilir
Raw SQL Maksimum performans Güvenlik riski (Injection)
Compiled Query Tekrar eden sorgularda hızlı Bakımı daha zordur

Güvenlik Uyarısı: Raw SQL kullanmanız gereken durumlarda asla kullanıcıdan gelen veriyi doğrudan sorgu metnine eklemeyin. Her zaman parametreli sorgular (FromSqlInterpolated) kullanın, aksi takdirde SQL Injection saldırılarına açık hale gelirsiniz.

Sıkça Sorulan Sorular

EF Core sorguları neden yavaş çalışır?

Sorgular genellikle gereksiz veri çekimi veya eksik indeksleme nedeniyle yavaşlar. IQueryable yapısını kullanarak sorguyu veritabanı seviyesinde filtrelediğinizden emin olun.

Tracking ve No-Tracking nedir?

EF Core varsayılan olarak verileri izler (Tracking). Eğer veriyi sadece okuyacaksanız, AsNoTracking() kullanarak performansı artırabilirsiniz.

Asenkron sorgulama neden önemlidir?

ToListAsync() gibi asenkron metotlar, veritabanı yanıt beklerken uygulamanın ana iş parçacığını (thread) bloklamaz, bu da uygulamanın ölçeklenebilirliğini artırır.

Navigation Property nedir?

İlişkili tablolar arasındaki bağlantılardır. Örneğin, bir ürünün kategorisine erişmek için Include anahtar kelimesini kullanmalısınız.

Veritabanı bağlantı dizesini nasıl gizlerim?

Bağlantı dizelerini asla kaynak kodunuzda saklamayın. User Secrets veya ortam değişkenlerini (Environment Variables) kullanarak güvenli bir şekilde yönetin.

Entity Framework Core ile İleri Düzey Hata Ayıklama ve Loglama

Entity Framework Core kullanırken karşılaşılan en büyük zorluklardan biri, üretilen SQL sorgularının arka planda nasıl çalıştığını anlamaktır. Uygulamanızın performansını artırmak veya beklenmedik sonuçları gidermek için EF Core'un loglama mekanizmasını etkin bir şekilde kullanmalısınız.

SQL Sorgularını Konsola Yazdırma

Geliştirme aşamasında, veritabanına gönderilen sorguları anlık olarak görmek için DbContext yapılandırmasında LogTo metodunu kullanabilirsiniz. Bu, sorguların performansını analiz etmek için en hızlı yöntemdir.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=myServer;Database=myDb;Trusted_Connection=True;")
        .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
}

Bu yapılandırma ile tüm veritabanı işlemleriniz, parametre değerleri ve yürütme süreleri ile birlikte konsol ekranına dökülecektir. Üretim ortamında bu logları bir dosyaya veya merkezi bir loglama sistemine (Serilog, NLog gibi) yönlendirmeniz önerilir.

EF Core Projelerinde Birim Test (Unit Testing) Stratejileri

Veritabanı işlemleri içeren kodların test edilmesi, genellikle zorlayıcı kabul edilir. Ancak InMemory veritabanı sağlayıcısı sayesinde, gerçek bir SQL sunucusuna ihtiyaç duymadan sorgu mantığınızı test edebilirsiniz.

InMemory Provider ile Test Yazımı

Test projelerinizde Microsoft.EntityFrameworkCore.InMemory paketini kullanarak, sorgu filtreleme ve sıralama mantığınızı doğrulayabilirsiniz.

[Fact]
public void GetActiveUsers_ReturnsOnlyActive()
{
    var options = new DbContextOptionsBuilder()
        .UseInMemoryDatabase(databaseName: "TestDb")
        .Options;

    using (var context = new AppDbContext(options))
    {
        context.Users.Add(new User { Name = "Ali", IsActive = true });
        context.Users.Add(new User { Name = "Veli", IsActive = false });
        context.SaveChanges();
    }

    using (var context = new AppDbContext(options))
    {
        var activeUsers = context.Users.Where(u => u.IsActive).ToList();
        Assert.Single(activeUsers);
        Assert.Equal("Ali", activeUsers[0].Name);
    }
}

Bu yaklaşım, veritabanı bağlantısı gerektirmediği için testlerin çok hızlı çalışmasını sağlar. Ancak unutulmamalıdır ki, InMemory sağlayıcısı gerçek veritabanı kısıtlamalarını (Foreign Key, Unique Index vb.) simüle etmez; bu nedenle karmaşık sorgular için Testcontainers gibi kütüphanelerle Docker tabanlı entegrasyon testleri yapmanız daha sağlıklı sonuçlar verecektir.

İleri Seviye Sorgu İpuçları

  • Global Query Filters: Yazılımınızda "Soft Delete" (veriyi silmek yerine IsDeleted bayrağını true yapmak) kullanıyorsanız, OnModelCreating içerisinde global filtre tanımlayarak tüm sorgulara otomatik olarak Where(x => !x.IsDeleted) eklenmesini sağlayabilirsiniz.
  • Compiled Queries: Çok sık çalışan ve parametreleri değişen sorgular için EF.CompileQuery kullanarak sorgu planı oluşturma maliyetini düşürebilirsiniz.
  • Split Queries: İlişkili verileri çekerken oluşan "Cartesian Explosion" (Kartezyen Patlaması) sorununu önlemek için AsSplitQuery() metodunu kullanarak sorguyu parçalara ayırabilirsiniz.

Sonuç

C# ile Entity Framework kullanarak veri sorgulama, doğru teknikler uygulandığında oldukça güçlü ve esnek bir süreçtir. Bu rehberde öğrendiğiniz filtreleme, sıralama, projeksiyon ve performans optimizasyonu teknikleri, profesyonel projelerinizin temelini oluşturacaktır. Bir sonraki adım olarak, EF Core ile ilişkili verileri çekmek için kullanılan Eager Loading ve Lazy Loading konularını araştırmanızı öneririm.

Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamına geçmeden önce tüm veritabanı işlemlerinde hata yönetimi (try-catch), bağlantı havuzu yönetimi ve güvenlik denetimlerini (SQL injection koruması gibi) uyguladığınızdan emin olun.

Bu yazıya tepkinizi paylaşın:
Kerem Aydın

Mutfağından bahçesine, yaşamın her alanında hızlı ve etkili çözüm rehberleri hazırlıyorum. Bilgi kirliliğinden uzak, doğrudan sonuca odaklanan içerikler üretiyorum.

Yorumlar (0)

Yorum Yaz