Uygulama katmanı
Bağımlılık enjeksiyonu ve yaşam süreleri
Singleton, scoped ve transient: yanlış seçim sessiz veri sızıntısına veya çöken isteklere yol açar.
Kavramı anlayalım
Bağımlılık enjeksiyonunda (DI) bir sınıf ihtiyaç duyduğu nesneleri kendisi oluşturmaz; constructor’ında ister ve kapsayıcı sağlar. Böylece sınıf somut uygulamaya değil bir arayüze bağımlı olur ve testte sahte bir uygulama verilebilir.
Her servis bir yaşam süresiyle kaydedilir. Singleton: uygulama boyunca tek örnek; durumsuz ve iş parçacığı güvenli olmalıdır (yapılandırma, HttpClient fabrikası). Scoped: her HTTP isteği için bir örnek; DbContext bu türdendir, çünkü istek içinde değişiklikleri izler ve istek bitince bırakılır. Transient: her istendiğinde yeni örnek; hafif ve durumsuz yardımcılar için.
En tehlikeli hata ‘esir bağımlılık’tır (captive dependency): bir singleton, scoped bir servisi constructor’da alırsa o scoped örnek uygulama boyunca yaşar. DbContext bir singleton’a hapsolursa farklı kullanıcıların istekleri aynı bağlamı paylaşır; bu hem iş parçacığı hatalarına hem de veri karışmasına yol açar. ASP.NET Core geliştirme ortamında bunu ‘scope validation’ ile yakalar.
Yaşam süresi, bir nesnenin hangi istekler arasında paylaşıldığını belirler.
DbContext’i veya kullanıcıya özel durumu singleton bir servisin içinde tutmak.
Aynı konu. Üç farklı derinlik.
builder.Services.AddScoped<IPostQueries, PostQueries>();
public class PostsController(IPostQueries posts) : ControllerBase { … }Controller arayüzü ister; kapsayıcı her istekte bir PostQueries verir.
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.
Üretimde ara sıra ‘A second operation was started on this context instance before a previous operation completed’ hatası görülüyor. DbContext nerede yanlış kayıtlı olabilir?
Çözümü ve açıklamasını göster
DbContext’i alan bir servis singleton olarak kaydedilmiş (esir bağımlılık)
veya aynı istek içinde paralel Task.WhenAll ile aynı DbContext kullanılıyor.
DbContext iş parçacığı güvenli değildir: istek başına bir örnek, eşzamanlı kullanım yok.Bu hata DbContext’in aynı anda birden çok işlem tarafından kullanıldığını gösterir; çoğunlukla yanlış yaşam süresinden kaynaklanır.