My application using Azure SQL and Azure Blob Storage for some business requirements, most of the case need to support Atomic Transaction for both DB & Blob, if DB entry fails should rollback Blob as well(go all or no go), for DB side can use TransactionScope but Blob don't have any direct options, so decided to go 2 phase commit with help of IEnlistmentNotification interface, it working as expected but am trying to created common class/implementation to support all operations or at least few most used operations in Blob storage(upload, delete, SetMetadata ...), I don't get any idea about how to create some implementation, is this possible and any code samples available will help me lot.
Resource Manager
public class AzureBlobStorageResourceManager : IEnlistmentNotification, IDisposable
    {
        private List<AzureBlobStore> _operations;
        private bool _disposedValue;
        public void EnlistOperation(AzureBlobStore operation)
        {            
            if (_operations is null)
            {
                var currentTransaction = Transaction.Current;
                currentTransaction?.EnlistVolatile(this, EnlistmentOptions.None);
                _operations = new List<AzureBlobStore>();
            }
            _operations.Add(operation);
        }
        public void Commit(Enlistment enlistment)
        {
            foreach (var blobOperation in _operations)
            {
                blobOperation.Dispose();
            }
            enlistment.Done();
        }
        public void InDoubt(Enlistment enlistment)
        {
            foreach (var blobOperation in _operations)
            {
                blobOperation.RollBack().ConfigureAwait(false);
            }
            enlistment.Done();
        }
        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            try
            {
                foreach (var blobOperation in _operations)
                {
                    blobOperation.DoWork().ConfigureAwait(false);
                }
                preparingEnlistment.Prepared();
            }
            catch
            {                
                preparingEnlistment.ForceRollback();
            }
        }
        public void Rollback(Enlistment enlistment)
        {            
            foreach (var blobOperation in _operations)
            {
                blobOperation.RollBack().ConfigureAwait(false);
            }
            enlistment.Done();           
        }
       
        public void Dispose() => Dispose(true);
        
        protected virtual void Dispose(bool disposing)
        {
            if (_disposedValue) return;
            if (disposing)
            {
                foreach (var operation in _operations)
                    operation.Dispose();
            }
            _disposedValue = true;
        }
        ~AzureBlobStorageResourceManager() => Dispose(false);
    }
Actual Blob Operation
public class AzureBlobStore : IDisposable
    {
        private string _backupPath;
        private readonly string _blobName;
        private Stream _content;
        private bool _disposedValue;
        private BlobClient _blobClient;
        public AzureBlobStore(BlobContainerClient containerClient, string blobName, Stream content)
        {
            (_blobName, _content, _blobClient) = (blobName, content, containerClient.GetBlobClient(blobName));            
        }
        public async Task DoWork()
        {
            _content.Position = 0;
            await _blobClient.UploadAsync(_content).ConfigureAwait(false);
                       
            /*            
            await _blobClient.DeleteAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots).ConfigureAwait(false); 
            */
        }
        public async Task RollBack()
        {
            // Compensation logic for Upload
            await _blobClient.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots).ConfigureAwait(false);
            // Compensation logic for Delete
            /* await _blobClient.UploadAsync(_backupPath); */
        }
        public void Dispose() => Dispose(true);
       
        protected virtual void Dispose(bool disposing)
        {
            if (_disposedValue) return;
            if (disposing)
            {                
                _blobClient.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots);
            }
            _disposedValue = true;
        }
        ~AzureBlobStore() => Dispose(false);
    }
Code inside /* */ is another one Blob operation, am looking for common way to solve this.