Add SqlState and IsTransient to DbException (#39157)
authorShay Rojansky <roji@roji.org>
Sun, 12 Jul 2020 19:34:44 +0000 (22:34 +0300)
committerGitHub <noreply@github.com>
Sun, 12 Jul 2020 19:34:44 +0000 (21:34 +0200)
Closes #35601
Closes #34817

src/libraries/System.Data.Common/ref/System.Data.Common.cs
src/libraries/System.Data.Common/src/System/Data/Common/DbException.cs
src/libraries/System.Data.Common/tests/System/Data/Common/DbExceptionTests.cs

index c5a8f8d..95f28aa 100644 (file)
@@ -2206,6 +2206,8 @@ namespace System.Data.Common
         protected DbException(string? message) { }
         protected DbException(string? message, System.Exception? innerException) { }
         protected DbException(string? message, int errorCode) { }
+        public virtual bool IsTransient { get { throw null; } }
+        public virtual string? SqlState { get { throw null; } }
     }
     public static partial class DbMetaDataCollectionNames
     {
index d52693b..7021d06 100644 (file)
@@ -20,5 +20,28 @@ namespace System.Data.Common
         protected DbException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
         {
         }
+
+        /// <summary>
+        /// Indicates whether the error represented by this <see cref="DbException" /> could be a transient error, i.e. if retrying the triggering
+        /// operation may succeed without any other change. Examples of transient errors include failure to acquire a database lock, networking
+        /// issues. This allows automatic retry execution strategies to be developed without knowledge of specific database error codes.
+        /// </summary>
+        public virtual bool IsTransient => false;
+
+        /// <summary>
+        /// <para>
+        /// For database providers which support it, contains a standard SQL 5-character return code indicating the success or failure of
+        /// the database operation. The first 2 characters represent the <strong>class</strong> of the return code (e.g. error, success),
+        /// while the last 3 characters represent the <strong>subclass</strong>, allowing detection of error scenarios in a
+        /// database-portable way.
+        /// </para>
+        /// <para>
+        /// For database providers which don't support it, or for inapplicable error scenarios, contains <see langword="null" />.
+        /// </para>
+        /// </summary>
+        /// <returns>
+        /// A standard SQL 5-character return code, or <see langword="null" />.
+        /// </returns>
+        public virtual string? SqlState => null;
     }
 }
index 6399840..b473732 100644 (file)
@@ -1,6 +1,8 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+#nullable enable
+
 using Xunit;
 
 namespace System.Data.Common.Tests
@@ -32,6 +34,13 @@ namespace System.Data.Common.Tests
             Assert.Equal(4060, e.ErrorCode);
         }
 
+        [Fact]
+        public void IsTransient_is_false_by_default()
+            => Assert.False(new CustomDbException().IsTransient);
+
+        [Fact]
+        public void SqlState_is_null_by_default()
+            => Assert.Null(new CustomDbException().SqlState);
 
         private class CustomDbException : DbException
         {