Browse Source

Refactored and improved UOW. Added simple UOW middleware. Created a unit test for UOW.

pull/112/head
Halil İbrahim Kalkan 9 years ago
parent
commit
790ed478da
  1. 25
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUnitOfWorkMiddleware.cs
  2. 8
      src/Volo.Abp/Volo/Abp/Uow/AmbientUnitOfWork.cs
  3. 7
      src/Volo.Abp/Volo/Abp/Uow/ChildUnitOfWork.cs
  4. 2
      src/Volo.Abp/Volo/Abp/Uow/IBasicUnitOfWork.cs
  5. 2
      src/Volo.Abp/Volo/Abp/Uow/IDatabaseApiContainer.cs
  6. 41
      src/Volo.Abp/Volo/Abp/Uow/UnitOfWork.cs
  7. 19
      src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkManager.cs
  8. 43
      test/Volo.Abp.Tests/Volo/Abp/Uow/UnitOfWork_Ambient_Scope_Tests.cs

25
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUnitOfWorkMiddleware.cs

@ -0,0 +1,25 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Volo.Abp.Uow;
namespace Volo.Abp.AspNetCore.Mvc.Uow
{
class AbpUnitOfWorkMiddleware
{
private readonly RequestDelegate _next;
public AbpUnitOfWorkMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, IUnitOfWorkManager unitOfWorkManager)
{
using (var uow = unitOfWorkManager.Begin())
{
await _next(httpContext);
await uow.CompleteAsync();
}
}
}
}

8
src/Volo.Abp/Volo/Abp/Uow/AmbientUnitOfWork.cs

@ -6,18 +6,18 @@ namespace Volo.Abp.Uow
[ExposeServices(typeof(IAmbientUnitOfWork), typeof(IUnitOfWorkAccessor))] [ExposeServices(typeof(IAmbientUnitOfWork), typeof(IUnitOfWorkAccessor))]
public class AmbientUnitOfWork : IAmbientUnitOfWork, ISingletonDependency public class AmbientUnitOfWork : IAmbientUnitOfWork, ISingletonDependency
{ {
public IUnitOfWork UnitOfWork => _currentUowInfo.Value; public IUnitOfWork UnitOfWork => _currentUow.Value;
private readonly AsyncLocal<IUnitOfWork> _currentUowInfo; private readonly AsyncLocal<IUnitOfWork> _currentUow;
public AmbientUnitOfWork() public AmbientUnitOfWork()
{ {
_currentUowInfo = new AsyncLocal<IUnitOfWork>(); _currentUow = new AsyncLocal<IUnitOfWork>();
} }
public void SetUnitOfWork(IUnitOfWork unitOfWork) public void SetUnitOfWork(IUnitOfWork unitOfWork)
{ {
_currentUowInfo.Value = unitOfWork; _currentUow.Value = unitOfWork;
} }
} }
} }

7
src/Volo.Abp/Volo/Abp/Uow/ChildUnitOfWork.cs

@ -7,6 +7,8 @@ namespace Volo.Abp.Uow
{ {
internal class ChildUnitOfWork : IUnitOfWork internal class ChildUnitOfWork : IUnitOfWork
{ {
public Guid Id => _parent.Id;
public event EventHandler Completed; public event EventHandler Completed;
public event EventHandler<UnitOfWorkFailedEventArgs> Failed; public event EventHandler<UnitOfWorkFailedEventArgs> Failed;
public event EventHandler Disposed; public event EventHandler Disposed;
@ -60,5 +62,10 @@ namespace Volo.Abp.Uow
{ {
} }
public override string ToString()
{
return $"[UnitOfWork {Id}]";
}
} }
} }

2
src/Volo.Abp/Volo/Abp/Uow/IBasicUnitOfWork.cs

@ -7,6 +7,8 @@ namespace Volo.Abp.Uow
//TODO: Find a better naming :( //TODO: Find a better naming :(
public interface IBasicUnitOfWork : IDisposable public interface IBasicUnitOfWork : IDisposable
{ {
Guid Id { get; }
event EventHandler Completed; event EventHandler Completed;
event EventHandler<UnitOfWorkFailedEventArgs> Failed; event EventHandler<UnitOfWorkFailedEventArgs> Failed;

2
src/Volo.Abp/Volo/Abp/Uow/IDatabaseApiContainer.cs

@ -10,6 +10,6 @@ namespace Volo.Abp.Uow
IDatabaseApi FindDatabaseApi([NotNull] string id); IDatabaseApi FindDatabaseApi([NotNull] string id);
[NotNull] [NotNull]
IDatabaseApi GetOrAddDatabaseApi(string id, Func<IDatabaseApi> factory); IDatabaseApi GetOrAddDatabaseApi([NotNull] string id, [NotNull] Func<IDatabaseApi> factory);
} }
} }

41
src/Volo.Abp/Volo/Abp/Uow/UnitOfWork.cs

@ -8,6 +8,8 @@ namespace Volo.Abp.Uow
{ {
public class UnitOfWork : IUnitOfWork, ITransientDependency public class UnitOfWork : IUnitOfWork, ITransientDependency
{ {
public Guid Id { get; } = Guid.NewGuid();
public event EventHandler Completed; public event EventHandler Completed;
public event EventHandler<UnitOfWorkFailedEventArgs> Failed; public event EventHandler<UnitOfWorkFailedEventArgs> Failed;
public event EventHandler Disposed; public event EventHandler Disposed;
@ -27,23 +29,6 @@ namespace Volo.Abp.Uow
_databaseApis = new Dictionary<string, IDatabaseApi>(); _databaseApis = new Dictionary<string, IDatabaseApi>();
} }
public void Dispose()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
if (!_isCompleted || _exception != null)
{
OnFailed(_exception);
}
OnDisposed();
}
public void SaveChanges() public void SaveChanges()
{ {
foreach (var databaseApi in _databaseApis.Values) foreach (var databaseApi in _databaseApis.Values)
@ -122,6 +107,23 @@ namespace Volo.Abp.Uow
Disposed.InvokeSafely(this); Disposed.InvokeSafely(this);
} }
public void Dispose()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
if (!_isCompleted || _exception != null)
{
OnFailed(_exception);
}
OnDisposed();
}
private void PreventMultipleComplete() private void PreventMultipleComplete()
{ {
if (_isCompleted) if (_isCompleted)
@ -131,5 +133,10 @@ namespace Volo.Abp.Uow
_isCompleted = true; _isCompleted = true;
} }
public override string ToString()
{
return $"[UnitOfWork {Id}]";
}
} }
} }

19
src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkManager.cs

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -41,27 +40,13 @@ namespace Volo.Abp.Uow
_ambientUnitOfWork.SetUnitOfWork(unitOfWork); _ambientUnitOfWork.SetUnitOfWork(unitOfWork);
Debug.Assert(
_ambientUnitOfWork.UnitOfWork != null,
"_ambientUnitOfWork.UnitOfWork can not be null since it's set by _ambientUnitOfWork.SetUnitOfWork method!"
);
unitOfWork.Completed += (sender, args) =>
{
_ambientUnitOfWork.SetUnitOfWork(parentUow);
};
unitOfWork.Failed += (sender, args) =>
{
_ambientUnitOfWork.SetUnitOfWork(parentUow);
};
unitOfWork.Disposed += (sender, args) => unitOfWork.Disposed += (sender, args) =>
{ {
_ambientUnitOfWork.SetUnitOfWork(parentUow);
scope.Dispose(); scope.Dispose();
}; };
return _ambientUnitOfWork.UnitOfWork; return unitOfWork;
} }
} }
} }

43
test/Volo.Abp.Tests/Volo/Abp/Uow/UnitOfWork_Ambient_Scope_Tests.cs

@ -0,0 +1,43 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Modularity;
using Volo.Abp.TestBase;
using Xunit;
namespace Volo.Abp.Uow
{
public class UnitOfWork_Ambient_Scope_Tests : AbpIntegratedTest<IndependentEmptyModule>
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
public UnitOfWork_Ambient_Scope_Tests()
{
_unitOfWorkManager = ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
}
[Fact]
public async Task UnitOfWorkManager_Current_Should_Set_Correctly()
{
_unitOfWorkManager.Current.ShouldBeNull();
using (var uow1 = _unitOfWorkManager.Begin())
{
_unitOfWorkManager.Current.ShouldNotBeNull();
_unitOfWorkManager.Current.ShouldBe(uow1);
using (var uow2 = _unitOfWorkManager.Begin())
{
_unitOfWorkManager.Current.ShouldNotBeNull();
_unitOfWorkManager.Current.Id.ShouldBe(uow1.Id);
await uow2.CompleteAsync();
}
await uow1.CompleteAsync();
}
_unitOfWorkManager.Current.ShouldBeNull();
}
}
}
Loading…
Cancel
Save