@@ -19,25 +19,12 @@ public sealed class MySqlTransaction : DbTransaction
19
19
20
20
private async Task CommitAsync ( IOBehavior ioBehavior , CancellationToken cancellationToken )
21
21
{
22
- VerifyNotDisposed ( ) ;
23
- if ( Connection is null )
24
- throw new InvalidOperationException ( "Already committed or rolled back." ) ;
22
+ VerifyValid ( ) ;
25
23
26
- if ( Connection . CurrentTransaction == this )
27
- {
28
- using ( var cmd = new MySqlCommand ( "commit" , Connection , this ) )
29
- await cmd . ExecuteNonQueryAsync ( ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
30
- Connection . CurrentTransaction = null ;
31
- Connection = null ;
32
- }
33
- else if ( Connection . CurrentTransaction is object )
34
- {
35
- throw new InvalidOperationException ( "This is not the active transaction." ) ;
36
- }
37
- else if ( Connection . CurrentTransaction is null )
38
- {
39
- throw new InvalidOperationException ( "There is no active transaction." ) ;
40
- }
24
+ using ( var cmd = new MySqlCommand ( "commit" , Connection , this ) )
25
+ await cmd . ExecuteNonQueryAsync ( ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
26
+ Connection ! . CurrentTransaction = null ;
27
+ Connection = null ;
41
28
}
42
29
43
30
public override void Rollback ( ) => RollbackAsync ( IOBehavior . Synchronous , default ) . GetAwaiter ( ) . GetResult ( ) ;
@@ -49,25 +36,34 @@ private async Task CommitAsync(IOBehavior ioBehavior, CancellationToken cancella
49
36
50
37
private async Task RollbackAsync ( IOBehavior ioBehavior , CancellationToken cancellationToken )
51
38
{
52
- VerifyNotDisposed ( ) ;
53
- if ( Connection is null )
54
- throw new InvalidOperationException ( "Already committed or rolled back." ) ;
39
+ VerifyValid ( ) ;
55
40
56
- if ( Connection . CurrentTransaction == this )
57
- {
58
- using ( var cmd = new MySqlCommand ( "rollback" , Connection , this ) )
59
- await cmd . ExecuteNonQueryAsync ( ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
60
- Connection . CurrentTransaction = null ;
61
- Connection = null ;
62
- }
63
- else if ( Connection . CurrentTransaction is object )
64
- {
65
- throw new InvalidOperationException ( "This is not the active transaction." ) ;
66
- }
67
- else if ( Connection . CurrentTransaction is null )
68
- {
69
- throw new InvalidOperationException ( "There is no active transaction." ) ;
70
- }
41
+ using ( var cmd = new MySqlCommand ( "rollback" , Connection , this ) )
42
+ await cmd . ExecuteNonQueryAsync ( ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
43
+ Connection ! . CurrentTransaction = null ;
44
+ Connection = null ;
45
+ }
46
+
47
+ public void Release ( string savepointName ) => ExecuteSavepointAsync ( "release " , savepointName , IOBehavior . Synchronous , default ) . GetAwaiter ( ) . GetResult ( ) ;
48
+ public Task ReleaseAsync ( string savepointName , CancellationToken cancellationToken = default ) => ExecuteSavepointAsync ( "release " , savepointName , Connection ? . AsyncIOBehavior ?? IOBehavior . Asynchronous , cancellationToken ) ;
49
+
50
+ public void Rollback ( string savepointName ) => ExecuteSavepointAsync ( "rollback to " , savepointName , IOBehavior . Synchronous , default ) . GetAwaiter ( ) . GetResult ( ) ;
51
+ public Task RollbackAsync ( string savepointName , CancellationToken cancellationToken = default ) => ExecuteSavepointAsync ( "rollback to " , savepointName , Connection ? . AsyncIOBehavior ?? IOBehavior . Asynchronous , cancellationToken ) ;
52
+
53
+ public void Save ( string savepointName ) => ExecuteSavepointAsync ( "" , savepointName , IOBehavior . Synchronous , default ) . GetAwaiter ( ) . GetResult ( ) ;
54
+ public Task SaveAsync ( string savepointName , CancellationToken cancellationToken = default ) => ExecuteSavepointAsync ( "" , savepointName , Connection ? . AsyncIOBehavior ?? IOBehavior . Asynchronous , cancellationToken ) ;
55
+
56
+ private async Task ExecuteSavepointAsync ( string command , string savepointName , IOBehavior ioBehavior , CancellationToken cancellationToken )
57
+ {
58
+ VerifyValid ( ) ;
59
+
60
+ if ( savepointName is null )
61
+ throw new ArgumentNullException ( nameof ( savepointName ) ) ;
62
+ if ( savepointName . Length == 0 )
63
+ throw new ArgumentException ( "savepointName must not be empty" , nameof ( savepointName ) ) ;
64
+
65
+ using var cmd = new MySqlCommand ( command + "savepoint " + QuoteIdentifier ( savepointName ) , Connection , this ) ;
66
+ await cmd . ExecuteNonQueryAsync ( ioBehavior , cancellationToken ) . ConfigureAwait ( false ) ;
71
67
}
72
68
73
69
public new MySqlConnection ? Connection { get ; private set ; }
@@ -130,12 +126,20 @@ internal MySqlTransaction(MySqlConnection connection, IsolationLevel isolationLe
130
126
IsolationLevel = isolationLevel ;
131
127
}
132
128
133
- private void VerifyNotDisposed ( )
129
+ private void VerifyValid ( )
134
130
{
135
131
if ( m_isDisposed )
136
132
throw new ObjectDisposedException ( nameof ( MySqlTransaction ) ) ;
133
+ if ( Connection is null )
134
+ throw new InvalidOperationException ( "Already committed or rolled back." ) ;
135
+ if ( Connection . CurrentTransaction is null )
136
+ throw new InvalidOperationException ( "There is no active transaction." ) ;
137
+ if ( ! object . ReferenceEquals ( Connection . CurrentTransaction , this ) )
138
+ throw new InvalidOperationException ( "This is not the active transaction." ) ;
137
139
}
138
140
141
+ private static string QuoteIdentifier ( string identifier ) => "`" + identifier . Replace ( "`" , "``" ) + "`" ;
142
+
139
143
bool m_isDisposed ;
140
144
}
141
145
}
0 commit comments