{"id":7515,"date":"2026-08-28T22:47:40","date_gmt":"2026-08-29T05:47:40","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=7515"},"modified":"2026-08-29T12:15:32","modified_gmt":"2026-08-29T19:15:32","slug":"sqlclient-retry","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/sqlclient-retry\/","title":{"rendered":"Try the new SqlClient and Retry connections natively"},"content":{"rendered":"<p>The 2002 release of the original .NET Framework shipped ADO.NET and <code>System.Data.SqlClient<\/code>, the driver for SQL Server that gave .NET applications a standard connection approach. Over the years, updates, enhancements, and patches solidified these BCL classes as an integral dependency for millions of line-of-business applications that fueled innovation, business, and the world economy.<\/p>\n<p>Then in 2019, 17 years later, Microsoft introduced <code>Microsoft.Data.SqlClient<\/code>, a new .NET driver for SQL Server that was better in almost every way. Side-stepping the calcification all software inherits over time, but maintaining Microsoft&#8217;s critical commitment to backward compatibility, it replaced <code>System.Data.SqlClient<\/code> with an elegant new code base offering new features, security, and capabilities for the modern data-driven application.<\/p>\n<p><div class=\"alert alert-success\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Lightbulb\"><\/i><strong>To migrate from System.Data.SqlClient<\/strong><\/p>The Microsoft.Data.SqlClient namespace is essentially a new version of the System.Data.SqlClient namespace. Microsoft.Data.SqlClient generally maintains the same API and backward compatibility with System.Data.SqlClient. To migrate from System.Data.SqlClient to Microsoft.Data.SqlClient, for most applications, it&#8217;s simple. Add a NuGet dependency on Microsoft.Data.SqlClient and update references and using statements to Microsoft.Data.SqlClient.<\/div><\/p>\n<p>Based on telemetry, a startling number of applications haven&#8217;t read the memo and updated. So, let me take a moment to talk about an incredible feature of SqlClient we previewed in 2021: Configurable Retry Logic for <code>SqlConnection<\/code> and <code>SqlCommand<\/code>. This native implementation of resiliency bypassing the need for third-party libraries like Polly, providing incredible handling of transient availability right out of the box.<\/p>\n<h2>Configurable Retry Logic<\/h2>\n<p>Since reaching General Availability in SqlClient 4.0, configurable retry logic in <code>Microsoft.Data.SqlClient<\/code> has provided a practical answer to a simple reality: sometimes, stuff happens. The best hardware, the best software, and the best networks still experience hiccups. A brief outage, a dropped connection, or even someone tripping over a power cable can make the best-designed architecture fail for just a second.<\/p>\n<p>Retry logic is often the best answer for transient failures. It&#8217;s in the same category as closing and reopening the app, hitting refresh, or just turning something off and back on again. A simple retry is often all it takes to handle the intermittency of the real world. Its simplicity is its beauty; it doesn&#8217;t require additional bandwidth, redundancy, or a dead-letter queue. A well-defined retry policy can cover a myriad of troubles with just the right finesse.<\/p>\n<h3>Top features<\/h3>\n<p>Of course, every developer would expect to see the basics: fixed, incremental, and exponential retry intervals; configurable retry counts and delays; and support for both <code>SqlConnection<\/code> and <code>SqlCommand<\/code>. But SqlClient goes further with SQL-aware transient error detection, customizable transient error lists, command filtering, retry event notifications, and policies that can be configured in code or configuration. Because the retry happens inside the driver, it understands SQL Server in ways a general-purpose retry library simply cannot.<\/p>\n<p>In its most basic usage, the syntax is simple:<\/p>\n<pre><code class=\"language-csharp\">var options = new SqlRetryLogicOption\r\n{\r\n    NumberOfTries = 5,\r\n    DeltaTime = TimeSpan.FromSeconds(1),\r\n    MaxTimeInterval = TimeSpan.FromSeconds(20)\r\n};\r\n\r\nvar retryProvider =\r\n    SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);\r\n\r\nusing var connection = new SqlConnection(connectionString)\r\n{\r\n    RetryLogicProvider = retryProvider\r\n};\r\n\r\nawait connection.OpenAsync();\r\n<\/code><\/pre>\n<p>That&#8217;s it. If <code>OpenAsync()<\/code> encounters one of SqlClient&#8217;s recognized transient errors, it retries automatically using exponential backoff with built-in jitter. <code>NumberOfTries = 5<\/code> means one initial attempt plus up to four retries. Also,\u00a0 <code data-start=\"1006\" data-end=\"1031\">BaselineTransientErrors<\/code> now exposes the built-in transient-error list, making it easier to extend SQL-aware retry behavior.<\/p>\n<p><div class=\"alert alert-warning\">Retry is disabled by default; assigning a provider opts the connection or command into retry behavior.<\/div><\/p>\n<h3>Better than Polly?<\/h3>\n<p>Fundamentally, configurable retry in SqlClient solves the same retry problem as Polly, but there are key areas where being inside the SQL driver gives it an advantage. SqlClient already understands SQL Server transient errors, knows whether it is retrying a connection or command, avoids retrying commands inside active transactions, and exposes SQL-specific retry events and configuration.<\/p>\n<p><div class=\"alert alert-primary\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Polly remains the better choice when<\/strong><\/p>Polly remains the better choice when you need broader application resiliency like circuit breakers, fallbacks, hedging, or retry policies that span multiple dependencies. But for SQL retry alone, SqlClient is simpler, more focused, and more SQL-aware.<\/div><\/p>\n<p>What&#8217;s more, SqlClient&#8217;s retry provider is reusable. Define the policy once, then assign it directly to <code>SqlConnection<\/code> or <code>SqlCommand<\/code> without wrapping every database call in a separate resilience pipeline. The retry stays close to the failure, where the driver has the most context to decide what should happen next.<\/p>\n<p><div  class=\"d-flex justify-content-left\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/connect\/ado-net\/configurable-retry-logic-sqlclient-introduction?view=sql-server-ver17\" target=\"_blank\">Learn more about configurable retry<\/a><\/div><\/p>\n<h3>Getting Started<\/h3>\n<p>Start with an upgrade. If you are still using <code>System.Data.SqlClient<\/code> then its time to upgrade to <code>Microsoft.Data.SqlClient<\/code> and take advantage of decades of improvements and scores of enhancements like configurable retry. Now in version 7.x, <code>Microsoft.Data.SqlClient<\/code> is typically a drop-in replacement. In some cases, it can take a little well-deserved refactoring to get going, especially if new features are your motivation.<\/p>\n<p><div  class=\"d-flex justify-content-left\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/learn.microsoft.com\/en-us\/sql\/connect\/ado-net\/introduction-microsoft-data-sqlclient-namespace?view=sql-server-ver17\" target=\"_blank\">Learn more about SqlClient<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft.Data.SqlClient includes configurable retry logic for SqlConnection and SqlCommand, giving .NET applications built-in resilience for transient SQL Server failures without requiring Polly.<\/p>\n","protected":false},"author":96788,"featured_media":7520,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[444,1,690,672],"tags":[494],"class_list":["post-7515","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-azure-sql","category-drivers","category-sql-server-2025","tag-sqlclient"],"acf":[],"blog_post_summary":"<p>Microsoft.Data.SqlClient includes configurable retry logic for SqlConnection and SqlCommand, giving .NET applications built-in resilience for transient SQL Server failures without requiring Polly.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/7515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/96788"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=7515"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/7515\/revisions"}],"predecessor-version":[{"id":7527,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/7515\/revisions\/7527"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/7520"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=7515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=7515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=7515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}