ASP.NET Core + Dapper projelerinde sık karşılaşılan bir hata: “The semaphore timeout period has expired.”
Bu hata çoğunlukla yanlış bağlantı yönetiminden kaynaklanır. Birçok projede KapaliysaAc()
gibi metotlarla tek bir IDbConnection
nesnesi sürekli açık tutulur. Kısa vadede pratik gibi görünse de, uzun vadede bağlantı hataları, timeout sorunları ve performans kayıpları yaratır.
👉 Özetle: Uygulama SQL’den veri bekler, ama bağlantı bozulduğu veya yanıt geciktiği için işletim sistemi süreyi doldurur ve hata üretir.
KapaliysaAc()
private void KapaliysaAc()
{
if (db.State != ConnectionState.Open) db.Open();
}
Bu kodda amaç, aynı IDbConnection
nesnesini sürekli açık tutarak tekrar tekrar new SqlConnection
yazmaktan kaçınmaktır. Ama bu yöntem ciddi sorunlara yol açar.
KapaliysaAc()
Tehlikeli?.State = Open
görünebilirNetwork kesintisi veya SQL Server reseti sonrası bağlantı kopabilir. Ama SqlConnection.State
hala Open dönebilir. Kodun sorgu atar, ama aslında ölü bir connection üzerinden işlem yapmaya çalışır. Sonuç: Yanıt gelmez → timeout hatası.
ADO.NET connection pool kullanır: her new SqlConnection
aslında havuzdan sağlam bir bağlantı alır. Ama tek bir connection’ı hep açık tutarsan, havuz devreye giremez. Bozulmuş bir bağlantıyı kullanmaya devam edersin. Bu da transport-level error ve semaphore timeout hatalarının temel sebebidir.
SQL Server, firewall veya proxy uzun süre kullanılmayan bağlantıları kapatabilir. Ama nesne hala “açığım” der. İlk sorguda cevap gelmez → işletim sistemi bekler → süre dolunca “semaphore timeout expired”. Özellikle yüksek trafikli projelerde bu hata sık görülür.
Eğer uygulamanız 10 dakika boyunca hiç kullanılmazsa (hiç SQL sorgusu atılmazsa), bağlantı “idle” durumda kalır. Çoğu ortamda SQL Server veya aradaki ağ cihazları bu bağlantıyı otomatik olarak kapatır. Fakat uygulamanızdaki connection nesnesi hala Open
görünür. İlk yeni sorguda aslında ölü bir bağlantı kullanılacağı için “timeout / semaphore expired” hatası alırsınız.
👉 Çözüm: Her sorguda using
ile yeni bir connection açmak. Connection pool bozuk olanı atar, sağlam bir bağlantı verir. Böylece uygulama 10 dakika değil, 1 saat boşta kalsa bile sorun yaşamaz.
Bazı durumlarda hatanın tam metni “Execution Timeout Expired” olur. Bu durumda sorun genellikle iki ihtimalden kaynaklanır:
Her iki senaryoda da kalıcı çözüm, her sorguda using
ile yeni bir bağlantı açmak ve gerekiyorsa commandTimeout
parametresini ayarlamaktır.
using
PatternADO.NET’in connection pool özelliği sayesinde her new SqlConnection
hızlıdır. En güvenli yol: Her sorguda connection açıp kapatmak.
public IEnumerable GetDeals(Guid tenantId)
{
using var conn = new SqlConnection(_connectionString);
return conn.Query(
"SELECT Id, Adi FROM temel.Deals WHERE TenantId=@TenantId",
new { TenantId = tenantId }
);
}
SELECT *
yerine sadece gerekli kolonları seçin.commandTimeout
parametresini kullanın.KapaliysaAc()
gibi metotlar kısa vadede pratik görünse de, uzun vadede bağlantı problemleri ve timeout hataları üretir.
✅ Çözüm: Her sorguda using
ile connection açıp kapatın. Dapper ve ADO.NET’in connection pool mekanizması sayesinde bu yöntem hem güvenli, hem de performanslıdır.
👉 Bu rehberi ekibinle paylaşırsan, semaphore timeout ve execution timeout hatalarının büyük çoğunluğu kaybolacaktır.