Microsoft.Data.SqlClient ile Yerleşik Yeniden Deneme Mantığı
SQL Server bağlantılarında geçici hatalar kaçınılmazdır. Uzun yıllardır System.Data.SqlClient ile yaşayan.NET uygulamaları için Microsoft, Microsoft.Data.SqlClient içine gömülü bir yeniden deneme (retry) altyapısı sunuyor. Bu yazıda bu yerleşik özelliğin ne işe yaradığını, nasıl kullanıldığını ve Polly gibi genel amaçlı kütüphanelerle karşılaştırıldığında hangi durumlarda öne çıktığını Jerry Nixon’ın Azure SQL Dev Corner blogundaki açıklamalarına dayanarak özetliyorum.
System.Data.SqlClient’tan Microsoft.Data.SqlClient’a geçiş
2002’de.NET Framework ile birlikte gelen System.Data.SqlClient, uzun yıllar SQL Server bağlantısı için standart sürücüydü. Microsoft 2019’da, aynı API uyumluluğunu büyük ölçüde koruyan yeni bir sürücü olarak Microsoft.Data.SqlClient‘ı tanıttı. Yeni namespace, eskisinin işlevlerini geriye dönük uyumluluk çerçevesinde sürdürüyor; güvenlik ve yetenek tarafında ise modern uygulamalara odaklanan yeni bir kod tabanı getiriyor.
Geçiş çoğu uygulama için oldukça basit: Projeye Microsoft.Data.SqlClient NuGet bağımlılığını eklemek ve using ifadelerini yeni namespace’e güncellemek genellikle yetiyor. Nixon’a göre telemetri verileri, hala eski sürücüde kalan uygulama sayısının şaşırtıcı derecede yüksek olduğunu gösteriyor; oysa yeni sürücü, aşağıda ele alacağımız Configurable Retry Logic gibi kayda değer özellikler barındırıyor.
Configurable Retry Logic nedir?
2021’de önizleme olarak duyurulan ve Microsoft.Data.SqlClient 4.0 sürümünde genel kullanıma açılan Configurable Retry Logic, SqlConnection ve SqlCommand için yerleşik bir dayanıklılık mekanizması sağlıyor. Amaç net: Kısa süreli ağ kesintileri, düşen bağlantılar ya da anlık erişilebilirlik sorunları gibi geçici (transient) hatalarda üçüncü parti bir kütüphaneye ihtiyaç duymadan sürücünün kendisi yeniden denesin.
Yeniden deneme, geçici hataların büyük bölümü için pratik bir çözüm. Ek bant genişliği, dead-letter kuyruğu veya ayrı bir yedeklilik katmanı gerektirmediği için basit ama etkili. Doğru tanımlanmış bir retry politikası, gerçek dünyanın kesintilerini oldukça temiz biçimde absorbe edebiliyor.
Öne çıkan yetenekler
Beklenen temel özelliklerin hepsi burada:
- Sabit, artan (incremental) ve üstel (exponential) aralıklarla yeniden deneme.
- Yapılandırılabilir deneme sayısı ve gecikme süreleri.
- Hem
SqlConnectionhem deSqlCommandiçin destek.
Bunların ötesinde, sürücünün SQL Server’ı tanımasından doğan ek yetenekler var:
- SQL’e duyarlı geçici hata tespiti.
- Özelleştirilebilir geçici hata listeleri.
- Komut filtreleme.
- Retry olay bildirimleri.
- Kod veya konfigürasyon üzerinden tanımlanabilen politikalar.
Ayrıca BaselineTransientErrors, sürücünün varsayılan geçici hata listesini erişilebilir kılıyor; bu da SQL-farkındalıklı retry davranışını genişletmeyi kolaylaştırıyor.
Temel kullanım
En basit haliyle bir üstel geri çekilme (exponential backoff) politikası tanımlayıp SqlConnection‘a bağlamak yeterli:
var options = new SqlRetryLogicOption
{
NumberOfTries = 5,
DeltaTime = TimeSpan.FromSeconds(1),
MaxTimeInterval = TimeSpan.FromSeconds(20)
};
var retryProvider =
SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);
using var connection = new SqlConnection(connectionString)
{
RetryLogicProvider = retryProvider
};
await connection.OpenAsync();
OpenAsync() çağrısı, SqlClient’ın tanıdığı geçici hatalardan birine denk gelirse otomatik olarak yeniden deneniyor. NumberOfTries = 5 ifadesi bir ilk deneme ve ardından en fazla dört yeniden deneme demek. Üstel geri çekilme, dahili jitter ile birlikte uygulanıyor. Bir noktanın altını çizmek gerek: Retry davranışı varsayılan olarak kapalı, bağlantıya ya da komuta bir sağlayıcı atadığınızda devreye giriyor.
Polly ile karşılaştırma
Nixon’ın vurguladığı gibi, temelde SqlClient’ın retry sağlayıcısı Polly ile aynı problemi çözüyor. Ama sürücünün içinde çalışıyor olması bazı konularda avantaj sağlıyor:
- SQL Server’a özgü geçici hataları zaten tanıyor.
- Bir bağlantı mı yoksa komut mu yeniden denendiğini biliyor.
- Aktif bir transaction içindeki komutları yeniden denemekten kaçınıyor.
- SQL’e özel retry olayları ve konfigürasyon noktaları sunuyor.
Uygulama genelinde daha geniş bir dayanıklılık modeli gerektiğinde (circuit breaker, fallback, hedging veya birden fazla bağımlılığı kapsayan retry politikaları gibi) Polly hala daha uygun bir seçim. Yalnızca SQL retry ihtiyacı söz konusuysa SqlClient daha yalın, odaklı ve SQL-farkındalıklı bir yaklaşım sunuyor.
Sağlayıcının yeniden kullanılabilir olması da pratik bir kolaylık: Politikayı bir kez tanımlayıp aynı sağlayıcıyı farklı SqlConnection veya SqlCommand nesnelerine atayabilirsiniz. Böylece her veritabanı çağrısını ayrı bir dayanıklılık pipeline’ıyla sarmak zorunda kalmıyorsunuz; retry mantığı, bağlama en çok sahip olan sürücüye en yakın yerde çalışıyor.
Nereden başlamalı?
Hala System.Data.SqlClient kullanıyorsanız ilk adım güncelleme. 7.x sürümüne ulaşan Microsoft.Data.SqlClient, çoğu senaryoda drop-in bir yerine geçiş sunuyor; bazı durumlarda küçük bir refactoring gerekse de configurable retry gibi yeni özellikler bu eforu fazlasıyla karşılıyor.
Geçici hataların dağıtık sistemlerde hem uygulama hem de altyapı katmanında ele alınması gerektiğini düşünüyorsanız, tetikleme mekanizmalarında retry fırtınalarını kontrol altına almaya ilişkin şu yazıya da göz atabilirsiniz: Azure Functions’ta Retry Fırtınasını Durdurmak: Backoff ve Circuit Breaker.
Kaynaklar ve İleri Okuma
- Try the new SqlClient and Retry connections natively — Jerry Nixon, Azure SQL Dev Corner
- Configurable retry logic in Microsoft.Data.SqlClient (Microsoft Learn)
- Introduction to Microsoft.Data.SqlClient namespace (Microsoft Learn)
- Azure SQL Dev Corner blogu







3 comments