-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNestedTransactionManager.cs
78 lines (61 loc) · 2.8 KB
/
NestedTransactionManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class NestedTransactionManager : IDbContextTransactionManager
{
readonly ISqlServerConnection _sqlServerConnection;
public NestedTransactionManager(ISqlServerConnection sqlServerConnection)
{
// Dependency inject ISqlServerConnection, ISqlServerConnection is original IDbContextTransactionManager in EF Core 3.1 .
_sqlServerConnection = sqlServerConnection;
}
int Layer = 0;
public IDbContextTransaction CurrentTransaction => _sqlServerConnection.CurrentTransaction;
public IDbContextTransaction BeginTransaction()
{
if (Layer++ == 0)
_sqlServerConnection.BeginTransaction();
return new NestedTransation(this, Layer);
}
public async Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default)
{
if (Layer++ == 0)
await _sqlServerConnection.BeginTransactionAsync(cancellationToken);
return new NestedTransation(this, Layer);
}
public void CommitTransaction()
{
if (Layer-- <= 1)
_sqlServerConnection.CommitTransaction();
}
public Task CommitTransactionAsync(CancellationToken cancellationToken = default)
=> Layer-- <= 1
? _sqlServerConnection.CurrentTransaction.CommitAsync(cancellationToken)
: Task.CompletedTask;
public void ResetState() => _sqlServerConnection.ResetState();
public Task ResetStateAsync(CancellationToken cancellationToken = default) => _sqlServerConnection.ResetStateAsync(cancellationToken);
public void RollbackTransaction() => _sqlServerConnection.RollbackTransaction();
class NestedTransation : IDbContextTransaction
{
readonly NestedTransactionManager _manager;
readonly int _layer;
public NestedTransation(NestedTransactionManager manager, int layer)
{
_manager = manager;
_layer = layer;
}
bool Commited => _layer > _manager.Layer;
public Guid TransactionId => Transaction.TransactionId;
IDbContextTransaction Transaction => _manager.CurrentTransaction;
public void Commit() => _manager.CommitTransaction();
public Task CommitAsync(CancellationToken cancellationToken = default) => _manager.CommitTransactionAsync(cancellationToken);
public void Dispose()
{
if (!Commited && Transaction != null)
Transaction.Dispose();
}
public ValueTask DisposeAsync()
=> !Commited && Transaction != null
? Transaction.DisposeAsync()
: default;
public void Rollback() => Transaction.Rollback();
public Task RollbackAsync(CancellationToken cancellationToken = default) => Transaction.RollbackAsync(cancellationToken);
}
}