Add savepoint API to DbTransaction (#34561)
authorShay Rojansky <roji@roji.org>
Wed, 5 Aug 2020 19:02:13 +0000 (22:02 +0300)
committerGitHub <noreply@github.com>
Wed, 5 Aug 2020 19:02:13 +0000 (22:02 +0300)
Closes #33397

src/libraries/System.Data.Common/ref/System.Data.Common.cs
src/libraries/System.Data.Common/src/System/Data/Common/DbTransaction.cs

index a2f519c..51be327 100644 (file)
@@ -2441,6 +2441,13 @@ namespace System.Data.Common
         public virtual System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
         public abstract void Rollback();
         public virtual System.Threading.Tasks.Task RollbackAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
+        public virtual bool SupportsSavepoints { get { throw null; } }
+        public virtual System.Threading.Tasks.Task SaveAsync(string savepointName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
+        public virtual System.Threading.Tasks.Task RollbackAsync(string savepointName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
+        public virtual System.Threading.Tasks.Task ReleaseAsync(string savepointName, System.Threading.CancellationToken cancellationToken = default) { throw null; }
+        public virtual void Save(string savepointName) { throw null; }
+        public virtual void Rollback(string savepointName) { throw null; }
+        public virtual void Release(string savepointName) { throw null; }
     }
     public enum GroupByBehavior
     {
index fe357a6..8728590 100644 (file)
@@ -67,5 +67,121 @@ namespace System.Data.Common
                 return Task.FromException(e);
             }
         }
+
+        #region Savepoints
+
+        /// <summary>
+        /// Gets a value that indicates whether this <see cref="DbTransaction" /> instance supports database savepoints.
+        /// If <see langword="false" />, the methods <see cref="SaveAsync" />,
+        /// <see cref="RollbackAsync(string, System.Threading.CancellationToken)"/> and <see cref="ReleaseAsync" /> as
+        /// well as their synchronous counterparts are expected to throw <see cref="NotSupportedException" />.
+        /// </summary>
+        /// <returns>
+        /// <see langword="true" /> if this <see cref="DbTransaction"/> instance supports database savepoints; otherwise,
+        /// <see langword="false" />.
+        /// </returns>
+        public virtual bool SupportsSavepoints => false;
+
+        /// <summary>
+        /// Creates a savepoint in the transaction. This allows all commands that are executed after the savepoint was
+        /// established to be rolled back, restoring the transaction state to what it was at the time of the savepoint.
+        /// </summary>
+        /// <param name="savepointName">The name of the savepoint to be created.</param>
+        /// <param name="cancellationToken">
+        /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None" />.
+        /// </param>
+        /// <returns>A <see cref="Task " /> representing the asynchronous operation.</returns>
+        public virtual Task SaveAsync(string savepointName, CancellationToken cancellationToken = default)
+        {
+            if (cancellationToken.IsCancellationRequested)
+            {
+                return Task.FromCanceled(cancellationToken);
+            }
+
+            try
+            {
+                Save(savepointName);
+                return Task.CompletedTask;
+            }
+            catch (Exception e)
+            {
+                return Task.FromException(e);
+            }
+        }
+
+        /// <summary>
+        /// Rolls back all commands that were executed after the specified savepoint was established.
+        /// </summary>
+        /// <param name="savepointName">The name of the savepoint to roll back to.</param>
+        /// <param name="cancellationToken">
+        /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None" />.
+        /// </param>
+        /// <returns>A <see cref="Task " /> representing the asynchronous operation.</returns>
+        public virtual Task RollbackAsync(string savepointName, CancellationToken cancellationToken = default)
+        {
+            if (cancellationToken.IsCancellationRequested)
+            {
+                return Task.FromCanceled(cancellationToken);
+            }
+
+            try
+            {
+                Rollback(savepointName);
+                return Task.CompletedTask;
+            }
+            catch (Exception e)
+            {
+                return Task.FromException(e);
+            }
+        }
+
+        /// <summary>
+        /// Destroys a savepoint previously defined in the current transaction. This allows the system to
+        /// reclaim some resources before the transaction ends.
+        /// </summary>
+        /// <param name="savepointName">The name of the savepoint to release.</param>
+        /// <param name="cancellationToken">
+        /// An optional token to cancel the asynchronous operation. The default value is <see cref="CancellationToken.None" />.
+        /// </param>
+        /// <returns>A <see cref="Task " /> representing the asynchronous operation.</returns>
+        public virtual Task ReleaseAsync(string savepointName, CancellationToken cancellationToken = default)
+        {
+            if (cancellationToken.IsCancellationRequested)
+            {
+                return Task.FromCanceled(cancellationToken);
+            }
+
+            try
+            {
+                Release(savepointName);
+                return Task.CompletedTask;
+            }
+            catch (Exception e)
+            {
+                return Task.FromException(e);
+            }
+        }
+
+        /// <summary>
+        /// Creates a savepoint in the transaction. This allows all commands that are executed after the savepoint was
+        /// established to be rolled back, restoring the transaction state to what it was at the time of the savepoint.
+        /// </summary>
+        /// <param name="savepointName">The name of the savepoint to be created.</param>
+        public virtual void Save(string savepointName) => throw new NotSupportedException();
+
+        /// <summary>
+        /// Rolls back all commands that were executed after the specified savepoint was established.
+        /// </summary>
+        /// <param name="savepointName">The name of the savepoint to roll back to.</param>
+        public virtual void Rollback(string savepointName) => throw new NotSupportedException();
+
+        /// <summary>
+        /// Destroys a savepoint previously defined in the current transaction. This allows the system to
+        /// reclaim some resources before the transaction ends.
+        /// </summary>
+        /// <param name="savepointName">The name of the savepoint to release.</param>
+        public virtual void Release(string savepointName) {}
+
+        #endregion
     }
 }