• 30.10.2026 19:14:38
  • İbrahim Gökyar

Entity Framework Core (EF Core) ile performans, izleme, veri modelleme ve EF6'dan geçiş adımlarını açıklayan pratik bir rehber. Kod örnekleri ve test, migration, raw SQL ipuçları içerir.

Entity Framework Core ile Verimli Veri Erişimi: Modern Rehber ve Geçiş Stratejileri

Bu makalede Entity Framework Core (EF Core) kullanarak üretimde güvenli, performanslı ve test edilebilir veri erişim katmanları nasıl kurulur, eski EF6 projelerinden EF Core'a nasıl geçiş yapılır ve sık yapılan hatalardan nasıl kaçınılır anlatılacak. Hedef kitle .NET geliştiricileri; temel ORM bilgisi olduğunu varsayıyoruz.

Neden EF Core? Güncel Yaklaşım ve Avantajlar

EF Core, .NET uygulamaları için hafif, genişletilebilir ve platformlar arası bir ORM'dir. EF6'ya kıyasla daha modern altyapı, daha iyi LINQ optimizasyonu, çarpıcı performans iyileştirmeleri ve güncel .NET sürümleriyle uyumluluk sunar. Ayrıca Azure ve konteyner senaryolarında sorunsuz çalışır.

Bununla birlikte EF Core, tasarım kararları açısından EF6'dan farklılıklar içerir: bazı API'lar değişti, davranışlar farklılaştı (ör. cascade delete varsayılanları), ve bazı eski özellikler ilk sürümlerde eksikti ancak güncellemelerle büyük ölçüde kapatıldı. Bu nedenle geçiş planı ve testler kritik.

Modelleme ve Veri Şeması: En İyi Uygulamalar

İyi bir modelleme, veri katmanının ilerideki bakımını ve performansını doğrudan etkiler. Entity sınıflarını mümkün olduğunca POCO olarak tutun; veri anotasyonları veya Fluent API ile kesin kuralları tanımlayın. Özellikle ilişkilerde yükleme davranışını (eager, lazy, explicit) netleştirmek önemlidir.

Aşağıdaki kurallar genelde işe yarar:

  • DbContext ömrünü kısa tutun; scoped yaşam döngüsü web uygulamaları için uygundur.
  • Navigation property'leri sanal bırakıp lazy loading kullanımı dikkatli planlanmalı; üretimde eager loading veya explicit loading tercih edilebilir.
  • Value object'leri owned entity olarak modelleyin; bu, normalleştirme ve sorgu optimizasyonu açısından faydalıdır.

Performans: Sorgular, İzleme ve Batching

EF Core ile performansı artırmak için birkaç temel ilke vardır: gereksiz izlemeyi devre dışı bırakın, sorgu projeksiyonları kullanın, büyük güncellemelerde batch işlemlerinden yararlanın ve N+1 sorgu problemlerini çözün.

Örnek: sadece gösterim amaçlı veri çekiyor ancak değiştirmiyorsanız AsNoTracking() kullanın:

<!-- HTML-escaped C# örneği -->
var products = await context.Products
    .AsNoTracking()
    .Where(p => p.IsActive)
    .Select(p => new { p.Id, p.Name, p.Price })
    .ToListAsync();

Batching: EF Core, SaveChanges() sırasında değişiklikleri tek seferde veritabanına gönderir. Büyük veri güncellemelerinde transaction içinde toplu SQL veya üçüncü parti kütüphanelerle (ör. EFCore.BulkExtensions) performans kazanabilirsiniz. Ancak her zaman transaction ve hata durumlarını dikkate alın.

Raw SQL ve Komutların Akıllı Kullanımı

Bazen LINQ sorguları karmaşık performans gereksinimlerini karşılamaz; bu durumlarda raw SQL veya Dapper gibi hafif araçlar avantaj sağlar. EF Core, FromSqlRaw/FromSqlInterpolated ile ham sorgu çalıştırmaya izin verirken parametre enjeksiyonunu doğru yönetirseniz güvenlidir.

<!-- HTML-escaped C# örneği -->
var reports = await context.Sales
    .FromSqlInterpolated($"SELECT * FROM Sales WHERE Date >= {start} AND Date <= {end}")
    .AsNoTracking()
    .ToListAsync();

Not: FromSql* ile gelen veriler entity türüne tam eşlenmelidir veya keyless (Query) tipler kullanılmalıdır. Karmaşık işlemler için stored procedure çağrıları da mümkündür ancak test edilebilirlik ve taşınabilirlik açısından dikkatli değerlendirin.

Migrations, Deployment ve CI/CD Entegrasyonu

Migration'lar veritabanı şemasını kodla senkron tutmanın standart yöntemidir. EF Core migrations, kaynak kontrolüne konulmalı ve CI sürecinde uygulanmalıdır. Otomatik migration uygulama bazı durumlarda cazip olsa da production ortamında manuel onaylı deploy çoğu kuruluş için daha güvenlidir.

İpuçları:

  • Migra­tion dosyalarını küçük, anlamlı adımlarla oluşturun.
  • Veri taşıma (data migration) gerekiyorsa idempotent scriptler yazın ve test veritabanlarında doğrulayın.
  • CI/CD pipeline'ında migration'ı bir adım olarak ekleyin; rollback senaryolarını planlayın.

Test Edilebilirlik: Unit Test ve Integration Test Stratejileri

Veri katmanı test edilirken in-memory provider (InMemory) kolaylık sağlar ama davranış farkları olabilir; özellikle SQL sorgu üretilmesi ve ilişkilerde farklı sonuçlar görebilirsiniz. Bu nedenle iki seviyeli test stratejisi öneririm:

  • Unit testler için repository/servis seviyesinde DbContext bağımlılığını mock'layın veya in-memory provider kullanın.
  • Integration testler için SQLite (file veya in-memory, ama gerçek SQL semantiği veren) kullanarak migration'ları uygulayın ve sorgu sonuçlarını doğrulayın.

Örnek: Integration test'te SQLite kullanımı

<!-- HTML-escaped C# örneği -->
var options = new DbContextOptionsBuilder<AppDbContext>()
    .UseSqlite("DataSource=:memory:")
    .Options;

using var context = new AppDbContext(options);
context.Database.OpenConnection();
context.Database.EnsureCreated();
// test senaryoları...

EF6'dan EF Core'a Geçiş: Pratik Adımlar

Eski bir proje EF6 kullanıyorsa geçiş planı aşağıdaki aşamalarla yönetilmelidir. Geçiş genellikle büyük bir refaktör değil; planlı ve kademeli yapılır.

Adımlar:

  • Bağımsızlık: İş mantığını DbContext'e sıkı bağlamayın; repository veya servis katmanlarıyla soyutlayın.
  • API farklılıklarını tespit edin: bazı EF6 API'ları EF Core'da farklı ya da yok. Örneğin ObjectContext, EDMX yaklaşımları ve bazı konfigürasyon modellemeleri yeniden ele alınmalı.
  • Testler: Mevcut testleri genişleterek geçiş sırasında regresyonları yakalayın.
  • Kademeli geçiş: Önce read-only senaryoları EF Core'a taşıyıp performans/uyumluluk testleri yapın, ardından write yollarını taşıyın.

Ayrıca veritabanı sağlayıcı uyumluluğunu kontrol edin (ör. SQL Server sürümleri, PostgreSQL sağlayıcıları). EF Core, farklı sağlayıcılar için behavior farklılıkları sergileyebilir.

Sık Sorulan Sorular

1. EF Core kullanırken ne zaman AsNoTracking tercih etmeliyim?

Okuma ağırlıklı, değişiklik yapılmayacak sorgularda AsNoTracking() kullanın. Bu, bellekte takip (change tracking) maliyetini ortadan kaldırır ve büyük veri listelerinde önemli performans kazanımları sağlar. Ancak, sonrasında entity üzerinde değişiklik yapıp SaveChanges() çağıracaksanız izlemeyi tekrar sağlamalısınız.

2. Lazy loading her zaman kötü mü?

Lazy loading faydalı olabilir, fakat N+1 sorgu sorunlarına yol açma riski taşır. Eğer lazy loading kullanacaksanız sorgularınızı profilleyip kritik yollar için Include ile eager loading veya explicit loading stratejileri belirleyin. Performansın kritik olduğu uçlarda eager loading daha öngörülebilirdir.

3. Migrations'ı production ortamında otomatik mi uygulamalıyım?

Genellikle otomatik migration uygulamak risklidir. Özellikle schema değişiklikleri veri migrasyonu gerektiriyorsa veya downtime planlaması yapılması gerekiyorsa manuel onaylı deployment tercih edin. CI/CD sürecinde migration script'leri oluşturup staging ortamında doğrulamak en güvenli yaklaşımdır.

İlgili Eğitim

Sonuç

EF Core, modern .NET uygulamaları için güçlü ve esnek bir ORM sunar. Performans, modelleme ve test edilebilirlik konularına dikkat ederek verimli veri katmanları kurabilirsiniz. Eski EF6 projelerinden geçiş yaparken kademeli bir plan, iyi test kapsamı ve provider uyumluluk kontrolleri başarıyı getirir. Bu makaledeki pratik ipuçları ve kod örnekleri, gerçek dünya senaryolarında yol gösterici olacaktır.

📚 Bu konuyu Opendart Akademi'de öğrenin: .NET Core eğitimi · .NET Core ReactJS eğitimi hakkında · YouTube video dersleri · Abone ol