Skip to content

Commit a0ffc3e

Browse files
committed
minor tweaks to multi-tenancy EF Core transaction usage
1 parent fd56a2c commit a0ffc3e

File tree

5 files changed

+26
-18
lines changed

5 files changed

+26
-18
lines changed

src/Persistence/Wolverine.EntityFrameworkCore/Codegen/EFCorePersistenceFrameProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public void ApplyTransactionSupport(IChain chain, IServiceContainer container)
133133
var createContext = typeof(CreateTenantedDbContext<>).CloseAndBuildAs<Frame>(dbContextType);
134134

135135
chain.Middleware.Insert(0, createContext);
136-
chain.Middleware.Insert(0, new EnrollTenantedDbContextInTransaction(dbContextType, chain.Idempotency));
136+
chain.Middleware.Insert(0, new StartDatabaseTransactionForDbContext(dbContextType, chain.Idempotency));
137137
}
138138
else
139139
{
@@ -173,7 +173,7 @@ public void ApplyTransactionSupport(IChain chain, IServiceContainer container, T
173173
{
174174
var createContext = typeof(CreateTenantedDbContext<>).CloseAndBuildAs<Frame>(dbType);
175175
chain.Middleware.Insert(0, createContext);
176-
chain.Middleware.Insert(0, new EnrollTenantedDbContextInTransaction(dbType, chain.Idempotency));
176+
chain.Middleware.Insert(0, new StartDatabaseTransactionForDbContext(dbType, chain.Idempotency));
177177
}
178178
else
179179
{

src/Persistence/Wolverine.EntityFrameworkCore/Codegen/EnrollTenantedDbContextInTransaction.cs renamed to src/Persistence/Wolverine.EntityFrameworkCore/Codegen/StartDatabaseTransactionForDbContext.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace Wolverine.EntityFrameworkCore.Codegen;
1111

12-
internal class EnrollTenantedDbContextInTransaction : AsyncFrame
12+
internal class StartDatabaseTransactionForDbContext : AsyncFrame
1313
{
1414
private readonly Type _dbContextType;
1515
private readonly IdempotencyStyle _idempotencyStyle;
@@ -18,7 +18,7 @@ internal class EnrollTenantedDbContextInTransaction : AsyncFrame
1818
private Variable _cancellation;
1919
private Variable? _context;
2020

21-
public EnrollTenantedDbContextInTransaction(Type dbContextType, IdempotencyStyle idempotencyStyle)
21+
public StartDatabaseTransactionForDbContext(Type dbContextType, IdempotencyStyle idempotencyStyle)
2222
{
2323
_dbContextType = dbContextType;
2424
_idempotencyStyle = idempotencyStyle;
@@ -31,19 +31,25 @@ public override void GenerateCode(GeneratedMethod method, ISourceWriter writer)
3131
// EF Core can only do eager idempotent checks
3232
if (_idempotencyStyle == IdempotencyStyle.Eager || _idempotencyStyle == IdempotencyStyle.Optimistic)
3333
{
34-
writer.Write($"await {_context.Usage}.{nameof(MessageContext.AssertEagerIdempotencyAsync)}({_cancellation.Usage});");
34+
writer.Write($"await {_context.Usage}.{nameof(MessageContext.AssertEagerIdempotencyAsync)}({_cancellation.Usage}).ConfigureAwait(false);");
3535
}
3636

3737
writer.Write($"BLOCK:if ({_dbContext.Usage}.Database.CurrentTransaction == null)");
38-
writer.Write($"await {_dbContext.Usage}.Database.BeginTransactionAsync({_cancellation.Usage});");
38+
writer.Write($"await {_dbContext.Usage}.Database.BeginTransactionAsync({_cancellation.Usage}).ConfigureAwait(false);");
3939
writer.FinishBlock();
40+
41+
// EF Core can only do eager idempotent checks
42+
if (_idempotencyStyle == IdempotencyStyle.Eager || _idempotencyStyle == IdempotencyStyle.Optimistic)
43+
{
44+
writer.Write($"await {_context.Usage}.{nameof(MessageContext.AssertEagerIdempotencyAsync)}({_cancellation.Usage}).ConfigureAwait(false);");
45+
}
4046

4147
Next?.GenerateCode(method, writer);
4248

43-
writer.Write($"await {_dbContext.Usage}.Database.CommitTransactionAsync({_cancellation.Usage});");
49+
writer.Write($"await {_dbContext.Usage}.Database.CommitTransactionAsync({_cancellation.Usage}).ConfigureAwait(false);");
4450
writer.FinishBlock();
4551
writer.Write($"BLOCK:catch ({typeof(Exception).FullNameInCode()})");
46-
writer.Write($"await {_dbContext.Usage}.Database.RollbackTransactionAsync({_cancellation.Usage});");
52+
writer.Write($"await {_dbContext.Usage}.Database.RollbackTransactionAsync({_cancellation.Usage}).ConfigureAwait(false);");
4753
writer.Write("throw;");
4854
writer.FinishBlock();
4955
}

src/Persistence/Wolverine.EntityFrameworkCore/Internals/TenantedDbContextBuilderByConnectionString.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ public class TenantedDbContextBuilderByConnectionString<T> : IDbContextBuilder<T
2424
private readonly IServiceProvider _serviceProvider;
2525
private readonly MultiTenantedMessageStore _store;
2626
private ImHashMap<string, string> _connectionStrings = ImHashMap<string, string>.Empty;
27+
private readonly IDomainEventScraper[] _domainScrapers;
2728

2829
// Going to assume that it's wolverine enabled here!
2930
public TenantedDbContextBuilderByConnectionString(IServiceProvider serviceProvider, MultiTenantedMessageStore store,
30-
Action<DbContextOptionsBuilder<T>, ConnectionString, TenantId> configuration)
31+
Action<DbContextOptionsBuilder<T>, ConnectionString, TenantId> configuration,
32+
IEnumerable<IDomainEventScraper> domainScrapers)
3133
{
3234
_serviceProvider = serviceProvider;
3335
_store = store;
36+
_domainScrapers = domainScrapers.ToArray();
3437

3538
_configuration = configuration;
3639
var optionsType = typeof(DbContextOptions<T>);
@@ -64,7 +67,7 @@ public async ValueTask<T> BuildAndEnrollAsync(MessageContext messaging, Cancella
6467
_configuration(builder, new ConnectionString(connectionString), new TenantId(messaging.TenantId));
6568
var dbContext = _constructor(builder.Options);
6669

67-
var transaction = new EfCoreEnvelopeTransaction(dbContext, messaging);
70+
var transaction = new EfCoreEnvelopeTransaction(dbContext, messaging, _domainScrapers);
6871

6972
await messaging.EnlistInOutboxAsync(transaction);
7073

src/Persistence/Wolverine.EntityFrameworkCore/Internals/TenantedDbContextBuilderByDbDataSource.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace Wolverine.EntityFrameworkCore.Internals;
1818
public class TenantedDbContextBuilderByDbDataSource<T> : IDbContextBuilder<T> where T : DbContext
1919
{
2020
private readonly Action<DbContextOptionsBuilder<T>, DbDataSource, TenantId> _configuration;
21+
private readonly IDomainEventScraper[] _domainScrapers;
2122

2223
private readonly Func<DbContextOptions<T>, T> _constructor;
2324

@@ -27,12 +28,14 @@ public class TenantedDbContextBuilderByDbDataSource<T> : IDbContextBuilder<T> wh
2728

2829
// Going to assume that it's wolverine enabled here!
2930
public TenantedDbContextBuilderByDbDataSource(IServiceProvider serviceProvider, MultiTenantedMessageStore store,
30-
Action<DbContextOptionsBuilder<T>, DbDataSource, TenantId> configuration)
31+
Action<DbContextOptionsBuilder<T>, DbDataSource, TenantId> configuration,
32+
IEnumerable<IDomainEventScraper> domainScrapers)
3133
{
3234
_serviceProvider = serviceProvider;
3335
_store = store;
3436

3537
_configuration = configuration;
38+
_domainScrapers = domainScrapers.ToArray();
3639
var optionsType = typeof(DbContextOptions<T>);
3740
var ctor = typeof(T).GetConstructors().FirstOrDefault(x =>
3841
x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == optionsType);
@@ -66,7 +69,7 @@ public async ValueTask<T> BuildAndEnrollAsync(MessageContext messaging, Cancella
6669

6770
var dbContext = _constructor(builder.Options);
6871

69-
var transaction = new EfCoreEnvelopeTransaction(dbContext, messaging);
72+
var transaction = new EfCoreEnvelopeTransaction(dbContext, messaging, _domainScrapers);
7073
await messaging.EnlistInOutboxAsync(transaction);
7174

7275
return dbContext;

src/Persistence/Wolverine.EntityFrameworkCore/WolverineEntityCoreExtensions.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public static IServiceCollection AddDbContextWithWolverineManagedMultiTenancy<T>
8282
$"Configured multi-tenanted usage of {typeof(T).FullNameInCode()} requires multi-tenanted Wolverine database storage");
8383
}
8484

85-
return new TenantedDbContextBuilderByConnectionString<T>(s, tenanted, dbContextConfiguration);
85+
return new TenantedDbContextBuilderByConnectionString<T>(s, tenanted, dbContextConfiguration, s.GetServices<IDomainEventScraper>());
8686
});
8787

8888
services.AddSingleton<IDbContextBuilder>(s => s.GetRequiredService<IDbContextBuilder<T>>());
@@ -92,10 +92,6 @@ public static IServiceCollection AddDbContextWithWolverineManagedMultiTenancy<T>
9292
services.AddSingleton<IResourceCreator, TenantedDbContextInitializer<T>>();
9393
}
9494

95-
// TODO -- need a multi-tenanted version of this
96-
// services.TryAddScoped(typeof(IDbContextOutbox<>), typeof(DbContextOutbox<>));
97-
// services.TryAddScoped<IDbContextOutbox, DbContextOutbox>();
98-
9995
return services;
10096
}
10197

@@ -140,7 +136,7 @@ public static IServiceCollection AddDbContextWithWolverineManagedMultiTenancyByD
140136
$"Configured multi-tenanted usage of {typeof(T).FullNameInCode()} requires multi-tenanted Wolverine database storage");
141137
}
142138

143-
return new TenantedDbContextBuilderByDbDataSource<T>(s, tenanted, dbContextConfiguration);
139+
return new TenantedDbContextBuilderByDbDataSource<T>(s, tenanted, dbContextConfiguration, s.GetServices<IDomainEventScraper>());
144140
});
145141

146142
services.AddSingleton<IDbContextBuilder>(s => s.GetRequiredService<IDbContextBuilder<T>>());

0 commit comments

Comments
 (0)