Skip to content

Commit 7ed3ea5

Browse files
committed
Add transactions to the MongoDbContext
1 parent 0ce9ad4 commit 7ed3ea5

File tree

4 files changed

+74
-18
lines changed

4 files changed

+74
-18
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using BackendFramework.Interfaces;
4+
using MongoDB.Driver;
5+
6+
namespace Backend.Tests.Mocks;
7+
8+
public class MongoDbContextMock : IMongoDbContext
9+
{
10+
public IMongoDatabase Db => throw new NotSupportedException();
11+
public Task<IMongoTransaction> BeginTransaction()
12+
{
13+
return Task.FromResult<IMongoTransaction>(new MongoTransactionMock());
14+
}
15+
16+
private sealed class MongoTransactionMock : IMongoTransaction
17+
{
18+
public Task CommitTransactionAsync()
19+
{
20+
return Task.CompletedTask;
21+
}
22+
23+
public Task AbortTransactionAsync()
24+
{
25+
return Task.CompletedTask;
26+
}
27+
28+
public void Dispose()
29+
{
30+
}
31+
}
32+
}

Backend/Contexts/MongoDbContext.cs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,44 @@
1-
using System;
2-
using System.Diagnostics.CodeAnalysis;
1+
using System.Threading.Tasks;
32
using BackendFramework.Interfaces;
43
using Microsoft.Extensions.Options;
54
using MongoDB.Driver;
65

7-
namespace BackendFramework.Contexts
6+
namespace BackendFramework.Contexts;
7+
8+
public class MongoDbContext : IMongoDbContext
89
{
9-
[ExcludeFromCodeCoverage]
10-
public class MongoDbContext : IMongoDbContext
10+
public IMongoDatabase Db { get; }
11+
12+
public MongoDbContext(IOptions<Startup.Settings> options)
13+
{
14+
var client = new MongoClient(options.Value.ConnectionString);
15+
Db = client.GetDatabase(options.Value.CombineDatabase);
16+
}
17+
18+
public async Task<IMongoTransaction> BeginTransaction()
1119
{
12-
private MongoClient _mongoClient { get; }
20+
var session = await Db.Client.StartSessionAsync();
21+
session.StartTransaction();
22+
return new MongoTransactionWrapper(session);
23+
}
24+
25+
private class MongoTransactionWrapper(IClientSessionHandle session) : IMongoTransaction
26+
{
27+
private readonly IClientSessionHandle _session = session;
1328

14-
public IMongoDatabase Db { get; }
29+
public Task CommitTransactionAsync()
30+
{
31+
return _session.CommitTransactionAsync();
32+
}
1533

16-
public MongoDbContext(IOptions<Startup.Settings> options)
34+
public Task AbortTransactionAsync()
1735
{
18-
_mongoClient = new MongoClient(options.Value.ConnectionString);
19-
Db = _mongoClient.GetDatabase(options.Value.CombineDatabase);
36+
return _session.AbortTransactionAsync();
2037
}
2138

2239
public void Dispose()
2340
{
24-
_mongoClient.Dispose();
25-
GC.SuppressFinalize(this);
41+
_session.Dispose();
2642
}
2743
}
2844
}
Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
using System;
2+
using System.Threading.Tasks;
23
using MongoDB.Driver;
34

4-
namespace BackendFramework.Interfaces
5+
namespace BackendFramework.Interfaces;
6+
7+
public interface IMongoDbContext
8+
{
9+
IMongoDatabase Db { get; }
10+
Task<IMongoTransaction> BeginTransaction();
11+
}
12+
13+
public interface IMongoTransaction : IDisposable
514
{
6-
public interface IMongoDbContext : IDisposable
7-
{
8-
IMongoDatabase Db { get; }
9-
}
15+
Task CommitTransactionAsync();
16+
Task AbortTransactionAsync();
1017
}

Backend/Startup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApp
350350

351351
// If an admin user has been created via the command line, treat that as a single action and shut the
352352
// server down so the calling script knows it's been completed successfully or unsuccessfully.
353-
var userRepo = app.ApplicationServices.GetService<IUserRepository>();
353+
using var startupScope = app.ApplicationServices.CreateAsyncScope();
354+
var userRepo = startupScope.ServiceProvider.GetService<IUserRepository>();
354355
if (userRepo is not null && CreateAdminUser(userRepo))
355356
{
356357
_logger.LogInformation("Stopping application");

0 commit comments

Comments
 (0)