-
Notifications
You must be signed in to change notification settings - Fork 6
/
MySqlSession.SessionTransaction.cs
150 lines (125 loc) · 4.79 KB
/
MySqlSession.SessionTransaction.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;
using System.Data;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using DevZest.Data.Primitives;
using MySql.Data.MySqlClient;
namespace DevZest.Data.MySql
{
partial class MySqlSession
{
private SessionTransaction _currentTransaction;
/// <inheritdoc/>
public sealed override int TransactionCount
{
get { return _currentTransaction == null ? 0 : 1; }
}
/// <inheritdoc/>
protected sealed override Transaction CurrentTransaction
{
get { return _currentTransaction; }
}
private sealed class SessionTransaction : Transaction
{
public static SessionTransaction Create(MySqlSession mySqlSession, IsolationLevel? isolation)
{
if (mySqlSession.TransactionCount == 0)
{
var connection = mySqlSession.Connection;
var transaction = isolation.HasValue ? connection.BeginTransaction(isolation.Value) : connection.BeginTransaction();
return new SessionTransaction(mySqlSession, transaction);
}
else
throw new NotSupportedException(DiagnosticMessages.NestedTransactionNotSupported);
}
public SessionTransaction(MySqlSession mySqlSession, MySqlTransaction mySqlTransaction)
{
MySqlSession = mySqlSession;
MySqlTransaction = mySqlTransaction;
Debug.Assert(CurrentTransaction == null);
CurrentTransaction = this;
}
public MySqlTransaction MySqlTransaction { get; }
private bool IsCurrent
{
get { return MySqlSession.CurrentTransaction == this; }
}
private void VerifyIsCurrent()
{
if (!IsCurrent)
throw new InvalidOperationException(DiagnosticMessages.VerifyIsCurrentTransaction);
}
private MySqlSession MySqlSession { get; }
protected sealed override DbSession<MySqlConnection, MySqlCommand, MySqlReader> GetDbSession()
{
return MySqlSession;
}
private SessionTransaction CurrentTransaction
{
get { return MySqlSession._currentTransaction; }
set { MySqlSession._currentTransaction = value; }
}
private bool _isDisposed;
public sealed override bool IsDisposed
{
get { return _isDisposed; }
}
public override string Name => null;
public override int Level => 0;
public sealed override void Dispose()
{
if (_isDisposed)
return;
PerformDispose();
CurrentTransaction = null;
_isDisposed = true;
}
protected sealed override Task PerformCommitAsync(CancellationToken ct)
{
VerifyIsCurrent();
VerifyNotFrozen();
MySqlTransaction.Commit();
_isFrozen = true;
return Task.CompletedTask;
}
protected sealed override Task PerformRollbackAsync(CancellationToken ct)
{
VerifyIsCurrent();
VerifyNotFrozen();
MySqlTransaction.Rollback();
_isFrozen = true;
return Task.CompletedTask;
}
protected override Task<int> ExecuteNonQueryAsync(MySqlCommand command, CancellationToken ct)
{
VerifyNotFrozen();
command.Transaction = MySqlTransaction;
return PerformExecuteNonQueryAsync(command, ct);
}
protected override Task<MySqlReader> ExecuteReaderAsync(Model model, MySqlCommand command, CancellationToken ct)
{
VerifyNotFrozen();
command.Transaction = MySqlTransaction;
return PerformExecuteReaderAsync(model, command, ct);
}
private bool _isFrozen;
private void VerifyNotFrozen()
{
if (_isFrozen)
throw new InvalidOperationException(DiagnosticMessages.VerifyNotFrozenTransaction);
}
private void PerformDispose()
{
if (_isFrozen)
return;
MySqlTransaction.Rollback();
}
}
/// <inheritdoc/>
protected sealed override ITransaction PerformBeginTransaction(IsolationLevel? isolation, string name = null)
{
return SessionTransaction.Create(this, isolation);
}
}
}