From b436e410cdf4f13fe3f4544b965a73c675cbdb17 Mon Sep 17 00:00:00 2001 From: vk Date: Thu, 23 Jan 2020 17:30:40 -0500 Subject: [PATCH 1/2] UnitOfWork: Check if transaction is active before committing or rolling back, fixes #211 --- .../App/Stubs/TransactionManagerStub.cs | 5 ++++- .../ISupportsTransactionStatus.cs | 17 ++++++++++++++++ .../TransactionManager.cs | 6 +++++- Src/SharpArch.RavenDb/TransactionManager.cs | 5 ++++- .../SharpArch.Web.AspNetCore.csproj | 1 + .../Transaction/UnitOfWorkHandler.cs | 20 ++++++++++++++++++- 6 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 Src/SharpArch.Domain/PersistenceSupport/ISupportsTransactionStatus.cs diff --git a/Samples/SharpArch.WebApi/App/Stubs/TransactionManagerStub.cs b/Samples/SharpArch.WebApi/App/Stubs/TransactionManagerStub.cs index 94ba23daa..88e870a22 100644 --- a/Samples/SharpArch.WebApi/App/Stubs/TransactionManagerStub.cs +++ b/Samples/SharpArch.WebApi/App/Stubs/TransactionManagerStub.cs @@ -7,7 +7,7 @@ namespace SharpArch.WebApi.Stubs { - public class TransactionManagerStub : ITransactionManager, IDisposable + public class TransactionManagerStub : ITransactionManager, IDisposable, ISupportsTransactionStatus { public const string TransactionIsolationLevel = "x-transaction-isolation-level"; public const string TransactionState = "x-transaction-result"; @@ -74,5 +74,8 @@ public void Dispose() { _transaction?.Dispose(); } + + /// + public bool IsActive => true; } } diff --git a/Src/SharpArch.Domain/PersistenceSupport/ISupportsTransactionStatus.cs b/Src/SharpArch.Domain/PersistenceSupport/ISupportsTransactionStatus.cs new file mode 100644 index 000000000..e8de21edc --- /dev/null +++ b/Src/SharpArch.Domain/PersistenceSupport/ISupportsTransactionStatus.cs @@ -0,0 +1,17 @@ +namespace SharpArch.Domain.PersistenceSupport +{ + using JetBrains.Annotations; + + + /// + /// Returns transaction status. + /// + [PublicAPI] + public interface ISupportsTransactionStatus + { + /// + /// Checks whether transaction is active or not. + /// + bool IsActive { get; } + } +} diff --git a/Src/SharpArch.NHibernate/TransactionManager.cs b/Src/SharpArch.NHibernate/TransactionManager.cs index 77189a318..94e95cf9c 100644 --- a/Src/SharpArch.NHibernate/TransactionManager.cs +++ b/Src/SharpArch.NHibernate/TransactionManager.cs @@ -4,6 +4,7 @@ using System.Data; using System.Threading; using System.Threading.Tasks; + using Domain.PersistenceSupport; using global::NHibernate; using JetBrains.Annotations; @@ -12,7 +13,7 @@ /// Transaction manager for NHibernate. /// [PublicAPI] - public class TransactionManager : INHibernateTransactionManager + public class TransactionManager : INHibernateTransactionManager, ISupportsTransactionStatus { /// [NotNull] @@ -44,5 +45,8 @@ public TransactionManager([NotNull] ISession session) /// public void FlushChanges() => Session.Flush(); + + /// + public bool IsActive => Session.Transaction.IsActive; } } diff --git a/Src/SharpArch.RavenDb/TransactionManager.cs b/Src/SharpArch.RavenDb/TransactionManager.cs index 88ebb2e0c..cb43b0ad7 100644 --- a/Src/SharpArch.RavenDb/TransactionManager.cs +++ b/Src/SharpArch.RavenDb/TransactionManager.cs @@ -16,7 +16,7 @@ namespace SharpArch.RavenDb /// /// [PublicAPI] - public class TransactionManager : ITransactionManager + public class TransactionManager : ITransactionManager, ISupportsTransactionStatus { [NotNull] readonly IDocumentSession _session; @@ -98,5 +98,8 @@ void ClearTransaction() _transaction?.Dispose(); _transaction = null; } + + /// + public bool IsActive => _transaction != null; } } diff --git a/Src/SharpArch.Web.AspNetCore/SharpArch.Web.AspNetCore.csproj b/Src/SharpArch.Web.AspNetCore/SharpArch.Web.AspNetCore.csproj index 8fe6ed171..e5d2c9ecd 100644 --- a/Src/SharpArch.Web.AspNetCore/SharpArch.Web.AspNetCore.csproj +++ b/Src/SharpArch.Web.AspNetCore/SharpArch.Web.AspNetCore.csproj @@ -33,6 +33,7 @@ + diff --git a/Src/SharpArch.Web.AspNetCore/Transaction/UnitOfWorkHandler.cs b/Src/SharpArch.Web.AspNetCore/Transaction/UnitOfWorkHandler.cs index 8bc70424a..dac88169d 100644 --- a/Src/SharpArch.Web.AspNetCore/Transaction/UnitOfWorkHandler.cs +++ b/Src/SharpArch.Web.AspNetCore/Transaction/UnitOfWorkHandler.cs @@ -6,6 +6,10 @@ namespace SharpArch.AspNetCore.Transaction { + using Infrastructure.Logging; + using Microsoft.AspNetCore.Http; + + /// /// Wraps controller actions marked with into transaction. /// @@ -15,10 +19,12 @@ namespace SharpArch.AspNetCore.Transaction [PublicAPI] public class UnitOfWorkHandler : ApplyTransactionFilterBase { + static readonly ILog Log = LogProvider.For(); + /// /// HttpContext key for Transaction Manger. /// - private const string TransactionManagerKey = "SharpArch.AspNetCore.UnitOfWork.TransactionManager"; + const string TransactionManagerKey = "SharpArch.AspNetCore.UnitOfWork.TransactionManager"; /// public override void OnActionExecuting(ActionExecutingContext context) @@ -33,6 +39,9 @@ public override void OnActionExecuting(ActionExecutingContext context) } /// + /// ITransactionManger was not found in HttpContext. + /// In can happen if third-party overwritten . + /// public override void OnActionExecuted(ActionExecutedContext context) { var transactionAttribute = GetTransactionAttribute(context); @@ -43,6 +52,15 @@ public override void OnActionExecuted(ActionExecutedContext context) throw new InvalidOperationException(nameof(ITransactionManager) + " was not found in HttpContext. Please contact SharpArch dev team."); + if (transactionManager is ISupportsTransactionStatus tranStatus) + { + if (!tranStatus.IsActive) + { + Log.Debug("Transaction is already closed"); + return; + } + } + if (context.Exception != null || transactionAttribute.RollbackOnModelValidationError && context.ModelState.IsValid == false) transactionManager.RollbackTransaction(); else From 10015503cc9f73f83c1d920692415d2368cfee81 Mon Sep 17 00:00:00 2001 From: vk Date: Thu, 23 Jan 2020 21:47:36 -0500 Subject: [PATCH 2/2] troubleshoot build script --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 1bd2c3ef3..bcbe3df00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,7 +38,7 @@ install: - ps: ./mssql-setup.ps1 build_script: - - ps: ./build.ps1 + - ps: ./build.ps1 -Verbosity Verbose test: off