Veri katmanı ve SQL
DbContext, bağlantı havuzu ve istek kapsamı
DbContext neden istek başına bir tanedir ve veritabanı bağlantıları neden tekrar kullanılır?
Kavramı anlayalım
DbContext, EF Core’da bir ‘iş birimi’dir: sorguları çalıştırır, yüklenen nesnelerdeki değişiklikleri izler ve SaveChanges çağrıldığında hepsini tek seferde veritabanına yazar. Hafif bir nesnedir ama iş parçacığı güvenli değildir ve izlediği nesneler zamanla birikir. Bu yüzden her HTTP isteği için yeni bir DbContext oluşturulur ve istek bitince bırakılır; AddDbContext bunu scoped yaşam süresiyle otomatik yapar.
Veritabanı bağlantısı açmak ise pahalıdır: ağ el sıkışması, kimlik doğrulama, oturum kurulumu. ADO.NET bağlantı havuzu kapatılan bağlantıları gerçekten kapatmaz, havuza geri koyar; bir sonraki istek aynı bağlantı dizesiyle hazır bir bağlantı alır. DbContext bağlantıyı yalnız sorgu çalışırken tutar ve hemen havuza bırakır.
Havuzun bir sınırı vardır (SQL Server istemcisinde varsayılan 100). Bağlantıyı uzun tutan işlemler, kapatılmayan okuyucular veya çok uzun transaction’lar havuzu tüketir ve yeni istekler ‘Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool’ hatasıyla bekler.
Yanlış yaşam süresi ve sızan bağlantılar, yük altında uygulamayı bir anda durdurur.
DbContext’i statik bir alanda veya singleton serviste tutmak.
Aynı konu. Üç farklı derinlik.
builder.Services.AddDbContext<PortfolioDbContext>(o =>
o.UseSqlServer(builder.Configuration.GetConnectionString("Portfolio")));DbContext scoped olarak kaydedilir; her istek kendi örneğini alır.
Bu sayfa gerçek bir sunucuya veya veritabanına bağlanmaz. Kod örnekleri .NET 8, Next.js ve SQL Server için temsilîdir; süreler simülasyondaki örnek değerlerdir, ölçüm değildir. Örnekleri yalnız kendi geliştirme ortamında dene; gerçek bağlantı dizesi, token veya parola paylaşma.
Önce kendin dene.
Yoğun saatlerde istekler 15 saniye bekleyip ‘connection pool’ zaman aşımı veriyor, ama SQL Server’ın CPU’su %10. İlk neye bakarsın?
Çözümü ve açıklamasını göster
Bağlantıyı uzun süre tutan kodlara:
- uzun transaction’lar veya transaction içinde dış servis çağrısı
- dispose edilmeyen DbContext/SqlConnection/DataReader
- senkron bekleme (.Result) nedeniyle tıkanan iş parçacıkları
SQL Server boşta, ama bağlantılar uygulamada kilitli kalıyor.Sorun veritabanı gücü değil, bağlantıların havuza geri dönmemesidir.