Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commitable transaction instead of DbTransaction #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using System.Transactions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Shop.Communication.DataAccess.Interfaces;
using Shop.Framework.UseCases.Interfaces.Services;
Expand All @@ -21,7 +22,7 @@ public override void Load(IServiceCollection services)
var context = sp.GetRequiredService<CommunicationDbContext>();
var connectionFactory = sp.GetRequiredService<IConnectionFactory>();

context.Database.UseTransaction(connectionFactory.GetTransaction());
context.Database.EnlistTransaction(connectionFactory.GetTransaction());

return context;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Data.Common;
using System;
using System.Data.Common;
using System.Transactions;
using Microsoft.Data.SqlClient;
using Shop.Framework.UseCases.Interfaces.Services;

Expand All @@ -12,7 +14,7 @@ public ConnectionFactory(string connectionString)
}

private DbConnection _connection;
private DbTransaction _transaction;
private Transaction _transaction;
private readonly string _connectionString;

public DbConnection GetConnection()
Expand All @@ -25,9 +27,14 @@ public DbConnection GetConnection()
return _connection;
}

public DbTransaction GetTransaction()
public Transaction GetTransaction()
{
return _transaction ??= GetConnection().BeginTransaction();
return _transaction ?? throw new InvalidOperationException("Transaction not initialized");
}

public void SetTransaction(Transaction transaction)
{
_transaction = transaction;
}

public bool IsConnectionOpened => _connection != null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System;
using System.Data.Common;
using System.Transactions;

namespace Shop.Framework.UseCases.Interfaces.Services
{
public interface IConnectionFactory : IDisposable
{
DbConnection GetConnection();
DbTransaction GetTransaction();
Transaction GetTransaction();
void SetTransaction(Transaction transaction);
bool IsConnectionOpened { get; }
bool IsTransactionStarted { get; }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using System.Transactions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Shop.Framework.UseCases.Interfaces.Services;
using Shop.Order.DataAccess.Interfaces;
Expand All @@ -21,7 +22,7 @@ public override void Load(IServiceCollection services)
var context = sp.GetRequiredService<OrderDbContext>();
var connectionFactory = sp.GetRequiredService<IConnectionFactory>();

context.Database.UseTransaction(connectionFactory.GetTransaction());
context.Database.EnlistTransaction(connectionFactory.GetTransaction());

return context;
});
Expand Down
2 changes: 1 addition & 1 deletion ModularMonolith/Shop.Tests.Unit/WorkflowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private ServiceCollection CreateServiceProvider(IConfiguration configuration)
services.AddMediatR(assemblies);
services.AddAutoMapper(assemblies);

services.AddScoped(typeof(IPipelineBehavior<,>), typeof(DbTransactionPipelineBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(CommitableTransactionPipelineBehavior<,>));

services.RegisterModule<CommunicationDataAccessModule>(configuration);
services.RegisterModule<OrderDataAccessModule>(configuration);
Expand Down
2 changes: 1 addition & 1 deletion ModularMonolith/Shop.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void ConfigureServices(IServiceCollection services)
services.RegisterModule<OrderContractModule>(Configuration);
services.RegisterModule<OrderUseCasesModule>(Configuration);

services.AddScoped(typeof(IPipelineBehavior<,>), typeof(DbTransactionPipelineBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(CommitableTransactionPipelineBehavior<,>));

var location = Assembly.GetExecutingAssembly().Location;
var assemblies = Directory.EnumerateFiles(Path.GetDirectoryName(location), "Shop*UseCases.dll")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using MediatR;
using Shop.Framework.UseCases.Interfaces.Services;
using Shop.Framework.UseCases.Interfaces.Transactions;

namespace Shop.Web.Utils
{
public class DbTransactionPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
public class CommitableTransactionPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>, ITransactionalRequest
{
private readonly IConnectionFactory _connectionFactory;

public DbTransactionPipelineBehavior(IConnectionFactory connectionFactory)
public CommitableTransactionPipelineBehavior(IConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
Expand All @@ -24,11 +25,15 @@ public async Task<TResponse> Handle(TRequest request, CancellationToken cancella
}

await using var connection = _connectionFactory.GetConnection();
await using var transaction = _connectionFactory.GetTransaction();

using var transaction = new CommittableTransaction(
new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted });

_connectionFactory.SetTransaction(transaction);

var result = await next();

await transaction.CommitAsync(cancellationToken);
transaction.Commit();

return result;
}
Expand Down