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.SqlServerpaketi. - Veritabanı bağlantı dizesini (connection string) tutan
appsettings.jsondosyası.
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
IsDeletedbayrağını true yapmak) kullanıyorsanız,OnModelCreatingiçerisinde global filtre tanımlayarak tüm sorgulara otomatik olarakWhere(x => !x.IsDeleted)eklenmesini sağlayabilirsiniz. - Compiled Queries: Çok sık çalışan ve parametreleri değişen sorgular için
EF.CompileQuerykullanarak 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.


Yorumlar (0)
Yorum Yaz