diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs index 552ce7e04e..43dedf916f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs @@ -46,7 +46,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow var options = CreateOptions(context, unitOfWorkAttr); //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware - if (_unitOfWorkManager.TryBeginReserved(AbpUnitOfWorkMiddleware.UnitOfWorkReservationName, options)) + if (_unitOfWorkManager.TryBeginReserved(UnitOfWork.UnitOfWorkReservationName, options)) { var result = await next(); if (!Succeed(result)) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs index bcef10ecd4..960c47b591 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs @@ -50,7 +50,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow var options = CreateOptions(context, unitOfWorkAttr); //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware - if (_unitOfWorkManager.TryBeginReserved(AbpUnitOfWorkMiddleware.UnitOfWorkReservationName, options)) + if (_unitOfWorkManager.TryBeginReserved(UnitOfWork.UnitOfWorkReservationName, options)) { var result = await next(); if (!Succeed(result)) diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs index c9ac1be509..aeb6f8a8c0 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs @@ -7,8 +7,6 @@ namespace Volo.Abp.AspNetCore.Uow { public class AbpUnitOfWorkMiddleware : IMiddleware, ITransientDependency { - public const string UnitOfWorkReservationName = "_AbpActionUnitOfWork"; - private readonly IUnitOfWorkManager _unitOfWorkManager; public AbpUnitOfWorkMiddleware(IUnitOfWorkManager unitOfWorkManager) @@ -18,7 +16,7 @@ namespace Volo.Abp.AspNetCore.Uow public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - using (var uow = _unitOfWorkManager.Reserve(UnitOfWorkReservationName)) + using (var uow = _unitOfWorkManager.Reserve(UnitOfWork.UnitOfWorkReservationName)) { await next(context); await uow.CompleteAsync(context.RequestAborted); diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs new file mode 100644 index 0000000000..061bc62018 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AspNetCoreUnitOfWorkTransactionBehaviourProvider.cs @@ -0,0 +1,41 @@ +using System; +using System.Net.Http; +using Microsoft.AspNetCore.Http; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace Volo.Abp.AspNetCore.Uow +{ + public class AspNetCoreUnitOfWorkTransactionBehaviourProvider : IUnitOfWorkTransactionBehaviourProvider, ITransientDependency + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public virtual bool? IsTransactional + { + get + { + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext == null) + { + return null; + } + + //IdentityServer endpoint (TODO: Better to move to the IDS module) + if (httpContext.Request.Path.Value?.StartsWith("/connect/", StringComparison.OrdinalIgnoreCase) == true) + { + return false; + } + + return !string.Equals( + httpContext.Request.Method, + HttpMethod.Get.Method, StringComparison.OrdinalIgnoreCase + ); + } + } + + public AspNetCoreUnitOfWorkTransactionBehaviourProvider(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs index a5e9a311db..22df5fddf5 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs @@ -133,6 +133,8 @@ namespace Volo.Abp.Uow.EntityFrameworkCore private async Task CreateDbContextAsync(IUnitOfWork unitOfWork) { + Logger.LogDebug($"Creating a new DbContext of type {typeof(TDbContext).FullName}"); + return unitOfWork.Options.IsTransactional ? await CreateDbContextWithTransactionAsync(unitOfWork) : unitOfWork.ServiceProvider.GetRequiredService(); diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkTransactionBehaviourProvider.cs new file mode 100644 index 0000000000..1db7dac938 --- /dev/null +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkTransactionBehaviourProvider.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Uow +{ + public interface IUnitOfWorkTransactionBehaviourProvider + { + bool? IsTransactional { get; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/NullUnitOfWorkTransactionBehaviourProvider.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/NullUnitOfWorkTransactionBehaviourProvider.cs new file mode 100644 index 0000000000..2b302d303a --- /dev/null +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/NullUnitOfWorkTransactionBehaviourProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Uow +{ + public class NullUnitOfWorkTransactionBehaviourProvider : IUnitOfWorkTransactionBehaviourProvider, ISingletonDependency + { + public bool? IsTransactional => null; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs index b4158229fe..d53acc8f66 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs @@ -11,6 +11,8 @@ namespace Volo.Abp.Uow { public class UnitOfWork : IUnitOfWork, ITransientDependency { + public const string UnitOfWorkReservationName = "_AbpActionUnitOfWork"; + public Guid Id { get; } = Guid.NewGuid(); public IAbpUnitOfWorkOptions Options { get; private set; } @@ -302,7 +304,7 @@ namespace Volo.Abp.Uow } } } - + protected virtual async Task CommitTransactionsAsync() { foreach (var transaction in GetAllActiveTransactionApis()) diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs index f5afcea494..f2ed948eb1 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs @@ -10,11 +10,16 @@ namespace Volo.Abp.Uow public class UnitOfWorkInterceptor : AbpInterceptor, ITransientDependency { private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IUnitOfWorkTransactionBehaviourProvider _transactionBehaviourProvider; private readonly AbpUnitOfWorkDefaultOptions _defaultOptions; - public UnitOfWorkInterceptor(IUnitOfWorkManager unitOfWorkManager, IOptions options) + public UnitOfWorkInterceptor( + IUnitOfWorkManager unitOfWorkManager, + IOptions options, + IUnitOfWorkTransactionBehaviourProvider transactionBehaviourProvider) { _unitOfWorkManager = unitOfWorkManager; + _transactionBehaviourProvider = transactionBehaviourProvider; _defaultOptions = options.Value; } @@ -26,7 +31,16 @@ namespace Volo.Abp.Uow return; } - using (var uow = _unitOfWorkManager.Begin(CreateOptions(invocation, unitOfWorkAttribute))) + var options = CreateOptions(invocation, unitOfWorkAttribute); + + //Trying to begin a reserved UOW by AbpUnitOfWorkMiddleware + if (_unitOfWorkManager.TryBeginReserved(UnitOfWork.UnitOfWorkReservationName, options)) + { + await invocation.ProceedAsync(); + return; + } + + using (var uow = _unitOfWorkManager.Begin(options)) { await invocation.ProceedAsync(); await uow.CompleteAsync(); @@ -42,7 +56,8 @@ namespace Volo.Abp.Uow if (unitOfWorkAttribute?.IsTransactional == null) { options.IsTransactional = _defaultOptions.CalculateIsTransactional( - autoValue: !invocation.Method.Name.StartsWith("Get", StringComparison.InvariantCultureIgnoreCase) + autoValue: _transactionBehaviourProvider.IsTransactional + ?? !invocation.Method.Name.StartsWith("Get", StringComparison.InvariantCultureIgnoreCase) ); }