diff --git a/common.props b/common.props
index 588e160..ef9649e 100644
--- a/common.props
+++ b/common.props
@@ -19,6 +19,7 @@
false
true
true
+ 7.1
diff --git a/src/Stove/Stove.csproj.DotSettings b/src/Stove/Stove.csproj.DotSettings
new file mode 100644
index 0000000..58ad6c8
--- /dev/null
+++ b/src/Stove/Stove.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ CSharp71
\ No newline at end of file
diff --git a/src/Stove/StoveComponentBase.cs b/src/Stove/StoveComponentBase.cs
index 7dd9803..c39d1ec 100644
--- a/src/Stove/StoveComponentBase.cs
+++ b/src/Stove/StoveComponentBase.cs
@@ -1,5 +1,7 @@
using System;
using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
using System.Transactions;
using Stove.Domain.Uow;
@@ -65,7 +67,7 @@ public IUnitOfWorkManager UnitOfWorkManager
///
public IMessageBus MessageBus { get; set; }
- public void UseUow(Action act)
+ protected void UseUow(Action act)
{
using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin())
{
@@ -75,6 +77,19 @@ public void UseUow(Action act)
}
}
+ protected Task UseUow(Func func, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin())
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+
+ return task;
+ }
+
protected void UseUow(Action act, IsolationLevel isolation)
{
using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions { IsolationLevel = isolation }))
@@ -85,6 +100,19 @@ protected void UseUow(Action act, IsolationLevel isolation)
}
}
+ protected Task UseUow(Func func, IsolationLevel isolation, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions { IsolationLevel = isolation }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+
+ return task;
+ }
+
protected void UseUow(Action act, bool isTransactional)
{
using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions { IsTransactional = isTransactional }))
@@ -95,6 +123,19 @@ protected void UseUow(Action act, bool isTransactional)
}
}
+ protected Task UseUow(Func func, bool isTransactional, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions { IsTransactional = isTransactional }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+
+ return task;
+ }
+
protected void UseUow(Action act, TransactionScopeOption scope)
{
using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
@@ -108,6 +149,22 @@ protected void UseUow(Action act, TransactionScopeOption scope)
}
}
+ protected Task UseUow(Func func, TransactionScopeOption scope, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
+ {
+ Scope = scope
+ }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+
+ return task;
+ }
+
protected void UseUow(Action act, IsolationLevel isolation, TransactionScopeOption scope)
{
using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
@@ -122,6 +179,23 @@ protected void UseUow(Action act, IsolationLevel isolation, TransactionScopeOpti
}
}
+ protected Task UseUow(Func func, IsolationLevel isolation, TransactionScopeOption scope, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
+ {
+ IsolationLevel = isolation,
+ Scope = scope
+ }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+
+ return task;
+ }
+
protected void UseUow(Action act, Action optsAction)
{
var options = new UnitOfWorkOptions();
@@ -136,6 +210,23 @@ protected void UseUow(Action act, Action optsAction)
}
}
+ protected Task UseUow(Func func, Action optsAction, CancellationToken cancellationToken = default)
+ {
+ var options = new UnitOfWorkOptions();
+
+ optsAction(options);
+
+ Task task;
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(options))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+
+ return task;
+ }
+
protected void UseUowIfNot(Action act)
{
if (UnitOfWorkManager.Current == null)
@@ -153,6 +244,26 @@ protected void UseUowIfNot(Action act)
}
}
+ protected Task UseUowIfNot(Func func, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ if (UnitOfWorkManager.Current == null)
+ {
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin())
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+ }
+ else
+ {
+ task = func();
+ }
+
+ return task;
+ }
+
protected void UseUowIfNot(Action act, bool isTransactional)
{
if (UnitOfWorkManager.Current == null)
@@ -173,6 +284,29 @@ protected void UseUowIfNot(Action act, bool isTransactional)
}
}
+ protected Task UseUowIfNot(Func func, bool isTransactional, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ if (UnitOfWorkManager.Current == null)
+ {
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
+ {
+ IsTransactional = isTransactional
+ }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+ }
+ else
+ {
+ task = func();
+ }
+
+ return task;
+ }
+
protected void UseUowIfNot(Action act, IsolationLevel isolation)
{
if (UnitOfWorkManager.Current == null)
@@ -193,6 +327,29 @@ protected void UseUowIfNot(Action act, IsolationLevel isolation)
}
}
+ protected Task UseUowIfNot(Func func, IsolationLevel isolation, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ if (UnitOfWorkManager.Current == null)
+ {
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
+ {
+ IsolationLevel = isolation
+ }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+ }
+ else
+ {
+ task = func();
+ }
+
+ return task;
+ }
+
protected void UseUowIfNot(Action act, IsolationLevel isolation, TransactionScopeOption scope)
{
if (UnitOfWorkManager.Current == null)
@@ -214,6 +371,30 @@ protected void UseUowIfNot(Action act, IsolationLevel isolation, TransactionScop
}
}
+ protected Task UseUowIfNot(Func func, IsolationLevel isolation, TransactionScopeOption scope, CancellationToken cancellationToken = default)
+ {
+ Task task;
+ if (UnitOfWorkManager.Current == null)
+ {
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(new UnitOfWorkOptions
+ {
+ IsolationLevel = isolation,
+ Scope = scope
+ }))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+ }
+ else
+ {
+ task = func();
+ }
+
+ return task;
+ }
+
protected void UseUowIfNot(Action act, Action optsAction)
{
var options = new UnitOfWorkOptions();
@@ -234,6 +415,29 @@ protected void UseUowIfNot(Action act, Action optsAction)
}
}
+ protected Task UseUowIfNot(Func func, Action optsAction, CancellationToken cancellationToken = default)
+ {
+ var options = new UnitOfWorkOptions();
+ optsAction(options);
+
+ Task task;
+ if (UnitOfWorkManager.Current == null)
+ {
+ using (IUnitOfWorkCompleteHandle uow = UnitOfWorkManager.Begin(options))
+ {
+ task = func();
+
+ uow.CompleteAsync(cancellationToken);
+ }
+ }
+ else
+ {
+ task = func();
+ }
+
+ return task;
+ }
+
protected void OnUowCompleted(Action action)
{
CurrentUnitOfWork.Completed += (sender, args) =>
diff --git a/test/Stove.Tests.SampleApplication/Domain/SomeDomainService.cs b/test/Stove.Tests.SampleApplication/Domain/SomeDomainService.cs
new file mode 100644
index 0000000..2facd57
--- /dev/null
+++ b/test/Stove.Tests.SampleApplication/Domain/SomeDomainService.cs
@@ -0,0 +1,103 @@
+using System.Threading;
+using System.Threading.Tasks;
+using System.Transactions;
+
+using Stove.Domain.Repositories;
+using Stove.Domain.Services;
+using Stove.Tests.SampleApplication.Domain.Entities;
+
+namespace Stove.Tests.SampleApplication.Domain
+{
+ public class SomeDomainService : DomainService
+ {
+ private readonly IRepository _messageRepository;
+ private readonly IRepository _repository;
+
+ public SomeDomainService(IRepository repository, IRepository messageRepository)
+ {
+ _repository = repository;
+ _messageRepository = messageRepository;
+ }
+
+ public User GetUserByName(string name)
+ {
+ User user = null;
+ UseUow(() =>
+ {
+ user = _repository.FirstOrDefault(x => x.Name == name);
+ });
+
+ return user;
+ }
+
+ public async Task GetUserByName_async(string name)
+ {
+ User user = null;
+ await UseUow(async () =>
+ {
+ user = await _repository.FirstOrDefaultAsync(x => x.Name == name);
+ }, CancellationToken.None);
+
+ return user;
+ }
+
+ public async Task GetUserByName_async_With_IsolationLevel(string name)
+ {
+ User user = null;
+
+ await UseUow(async () =>
+ {
+ user = await _repository.FirstOrDefaultAsync(x => x.Name == name);
+ }, IsolationLevel.ReadCommitted);
+
+ return user;
+ }
+
+ public User GetUserByName_with_isolationlevel(string name)
+ {
+ User user = null;
+
+ UseUow(() =>
+ {
+ user = _repository.FirstOrDefault(x => x.Name == name);
+ }, IsolationLevel.Chaos);
+
+ return user;
+ }
+
+ public User GetUserByName_isTransactional(string name)
+ {
+ User user = null;
+
+ UseUow(() =>
+ {
+ user = _repository.FirstOrDefault(x => x.Name == name);
+ }, true);
+
+ return user;
+ }
+
+ public async Task GetUserByName_async_isTransactional(string name)
+ {
+ User user = null;
+
+ await UseUow(async () =>
+ {
+ user = await _repository.FirstOrDefaultAsync(x => x.Name == name);
+ }, true);
+
+ return user;
+ }
+
+ public async Task CreateMessageAndGet(string message)
+ {
+ Message msg = null;
+ await UseUowIfNot(async () =>
+ {
+ msg = await _messageRepository.InsertAsync(new Message(message));
+ });
+
+ return msg;
+ }
+ }
+}
diff --git a/test/Stove.Tests.SampleApplication/StoveComponentBase_Tests.cs b/test/Stove.Tests.SampleApplication/StoveComponentBase_Tests.cs
new file mode 100644
index 0000000..f4e193b
--- /dev/null
+++ b/test/Stove.Tests.SampleApplication/StoveComponentBase_Tests.cs
@@ -0,0 +1,73 @@
+using System.Threading.Tasks;
+
+using Shouldly;
+
+using Stove.Tests.SampleApplication;
+using Stove.Tests.SampleApplication.Domain;
+using Stove.Tests.SampleApplication.Domain.Entities;
+
+using Xunit;
+
+namespace Stove.Tests
+{
+ public class StoveComponentBase_Tests : SampleApplicationTestBase
+ {
+ public StoveComponentBase_Tests()
+ {
+ Building(builder => { }).Ok();
+ }
+
+ [Fact]
+ public void UseUow_should_work()
+ {
+ User user = The().GetUserByName("Oğuzhan");
+ user.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task UseUow_async_should_work()
+ {
+ User user = await The().GetUserByName_async("Oğuzhan");
+ user.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task UseUow_with_IsolationLevel_should_work()
+ {
+ User user = await The().GetUserByName_async_With_IsolationLevel("Oğuzhan");
+ user.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public void UseUow_isTransactional_should_work()
+ {
+ User user = The().GetUserByName_isTransactional("Oğuzhan");
+ user.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public void UseUow_isolationLevel_should_work()
+ {
+ User user = The().GetUserByName_with_isolationlevel("Oğuzhan");
+ user.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task UseUow_async_isTransactional_should_work()
+ {
+ User user = await The().GetUserByName_async_isTransactional("Oğuzhan");
+ user.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task UseUow_and_auditing()
+ {
+ using (StoveSession.Use(266))
+ {
+ Message message = await The().CreateMessageAndGet("message");
+ message.Subject.ShouldBe("message");
+ message.CreatorUserId.ShouldBe(266);
+ }
+ }
+ }
+}