1- namespace ModularMonolith . APIs . BoundedContexts . BoardGames . EndPoints ;
1+ using Microsoft . EntityFrameworkCore . Storage ;
2+
3+ namespace ModularMonolith . APIs . BoundedContexts . BoardGames . EndPoints ;
24
35[ Register (
46 lifetime : ServiceLifetime . Scoped
57, methodNameHint : "AddBoardGameServices" ) ]
68public sealed class ApplyMegaDiscount (
79 BoardGamesDb db
8- , IIntegrationEventPublisher integrationEventPublisher )
10+ , [ FromKeyedServices ( nameof ( BoardGamesDb ) ) ] IOutboxSignal outboxSignal
11+ //, IIntegrationEventPublisher integrationEventPublisher
12+ )
913{
1014 public async Task < Results < Ok , BadRequest > > ExecuteAsync (
1115 decimal factor
@@ -19,20 +23,41 @@ decimal factor
1923 //}
2024 //await SaveChangesAsync(cancellationToken);
2125
22- // ✅ Use Set-based update (no materialization)
23- await db . BoardGames . ExecuteUpdateAsync ( s =>
24- s . SetProperty ( bg => bg . Price . Amount ,
25- bg => bg . Price . Amount * factor )
26- , cancellationToken
27- )
28- . ConfigureAwait ( false ) ;
29- // Now we need to update the entities that are in memory
30- // We can do this using an Integration Event
31- await integrationEventPublisher . PublishIntegrationEventAsync (
32- new GamesHaveChangedIntegrationEvent (
33- EventId : Guid . NewGuid ( )
34- ) , cancellationToken
35- ) . ConfigureAwait ( false ) ;
26+ IExecutionStrategy strategy = db . Database . CreateExecutionStrategy ( ) ;
27+
28+ await strategy . ExecuteAsync ( async ( ) =>
29+ {
30+ using IDbContextTransaction tx = await db . Database
31+ . BeginTransactionAsync ( cancellationToken )
32+ . ConfigureAwait ( false ) ;
33+
34+ try
35+ {
36+ // ✅ Use Set-based update (no materialization)
37+ await db . BoardGames . ExecuteUpdateAsync ( s =>
38+ s . SetProperty ( bg => bg . Price . Amount ,
39+ bg => bg . Price . Amount * factor )
40+ , cancellationToken
41+ )
42+ . ConfigureAwait ( false ) ;
43+
44+ // Now we need to update the entities that are in memory
45+ // We can do this using an Integration Event
46+ GamesHaveChangedIntegrationEvent @event =
47+ new GamesHaveChangedIntegrationEvent (
48+ EventId : Guid . NewGuid ( )
49+ ) ;
50+ await db . SaveChangesAsync ( @event , outboxSignal , cancellationToken )
51+ . ConfigureAwait ( false ) ;
52+
53+ await tx . CommitAsync ( cancellationToken ) ;
54+ }
55+ catch
56+ {
57+ await tx . RollbackAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
58+ throw ; // Re-throw to allow the execution strategy to retry
59+ }
60+ } ) ;
3661
3762 return TypedResults . Ok ( ) ;
3863 }
0 commit comments