Skip to content

Commit 35079ab

Browse files
authored
Merge pull request #63 from servicetitan/async-transaction-api
Async transaction api
2 parents baa386f + 2e2b42a commit 35079ab

16 files changed

Lines changed: 745 additions & 314 deletions

File tree

Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/Connection.cs

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Data;
99
using System.Data.Common;
1010
using FirebirdSql.Data.FirebirdClient;
11-
using Xtensive.Orm;
1211

1312
namespace Xtensive.Sql.Drivers.Firebird
1413
{
@@ -18,63 +17,52 @@ internal class Connection : SqlConnection
1817
private FbTransaction activeTransaction;
1918

2019
/// <inheritdoc/>
21-
public override DbConnection UnderlyingConnection
22-
{
23-
get { return underlyingConnection; }
24-
}
20+
public override DbConnection UnderlyingConnection => underlyingConnection;
2521

2622
/// <inheritdoc/>
27-
public override DbTransaction ActiveTransaction
28-
{
29-
get { return activeTransaction; }
30-
}
23+
public override DbTransaction ActiveTransaction => activeTransaction;
3124

3225
/// <inheritdoc/>
33-
public override DbParameter CreateParameter()
34-
{
35-
return new FbParameter();
36-
}
26+
public override DbParameter CreateParameter() => new FbParameter();
3727

3828
/// <inheritdoc/>
39-
public override void BeginTransaction()
40-
{
41-
BeginTransaction(IsolationLevel.Serializable);
42-
}
29+
public override void BeginTransaction() => BeginTransaction(IsolationLevel.Serializable);
4330

4431
/// <inheritdoc/>
4532
public override void BeginTransaction(IsolationLevel isolationLevel)
4633
{
4734
EnsureIsNotDisposed();
4835
EnsureTransactionIsNotActive();
4936

37+
var transactionOptions = CreateTransactionOptions(isolationLevel);
38+
activeTransaction = underlyingConnection.BeginTransaction(transactionOptions);
39+
}
40+
41+
private static FbTransactionOptions CreateTransactionOptions(IsolationLevel isolationLevel)
42+
{
5043
var transactionOptions = new FbTransactionOptions {WaitTimeout = TimeSpan.FromSeconds(10)};
5144
switch (SqlHelper.ReduceIsolationLevel(isolationLevel)) {
52-
case IsolationLevel.ReadCommitted:
53-
transactionOptions.TransactionBehavior = FbTransactionBehavior.ReadCommitted
54-
| FbTransactionBehavior.NoRecVersion
55-
| FbTransactionBehavior.Write
56-
| FbTransactionBehavior.NoWait;
57-
break;
58-
case IsolationLevel.Serializable:
59-
transactionOptions.TransactionBehavior = FbTransactionBehavior.Concurrency
60-
| FbTransactionBehavior.Write
61-
| FbTransactionBehavior.Wait;
62-
break;
45+
case IsolationLevel.ReadCommitted:
46+
transactionOptions.TransactionBehavior = FbTransactionBehavior.ReadCommitted
47+
| FbTransactionBehavior.NoRecVersion
48+
| FbTransactionBehavior.Write
49+
| FbTransactionBehavior.NoWait;
50+
break;
51+
case IsolationLevel.Serializable:
52+
transactionOptions.TransactionBehavior = FbTransactionBehavior.Concurrency
53+
| FbTransactionBehavior.Write
54+
| FbTransactionBehavior.Wait;
55+
break;
6356
}
64-
activeTransaction = underlyingConnection.BeginTransaction(transactionOptions);
57+
58+
return transactionOptions;
6559
}
6660

6761
/// <inheritdoc/>
68-
protected override void ClearActiveTransaction()
69-
{
70-
activeTransaction = null;
71-
}
62+
protected override void ClearActiveTransaction() => activeTransaction = null;
7263

7364
/// <inheritdoc/>
74-
protected override void ClearUnderlyingConnection()
75-
{
76-
underlyingConnection = null;
77-
}
65+
protected override void ClearUnderlyingConnection() => underlyingConnection = null;
7866

7967
/// <inheritdoc/>
8068
public override void MakeSavepoint(string name)

Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/Connection.cs

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using System.Data;
88
using System.Data.Common;
99
using System.Security;
10+
using System.Threading;
11+
using System.Threading.Tasks;
1012
using MySql.Data.MySqlClient;
1113

1214
namespace Xtensive.Sql.Drivers.MySql
@@ -17,23 +19,14 @@ internal class Connection : SqlConnection
1719
private MySqlTransaction activeTransaction;
1820

1921
/// <inheritdoc/>
20-
public override DbConnection UnderlyingConnection
21-
{
22-
get { return underlyingConnection; }
23-
}
22+
public override DbConnection UnderlyingConnection => underlyingConnection;
2423

2524
/// <inheritdoc/>
26-
public override DbTransaction ActiveTransaction
27-
{
28-
get { return activeTransaction; }
29-
}
25+
public override DbTransaction ActiveTransaction => activeTransaction;
3026

3127
/// <inheritdoc/>
3228
[SecuritySafeCritical]
33-
public override DbParameter CreateParameter()
34-
{
35-
return new MySqlParameter();
36-
}
29+
public override DbParameter CreateParameter() => new MySqlParameter();
3730

3831
/// <inheritdoc/>
3932
[SecuritySafeCritical]
@@ -58,46 +51,76 @@ public override void BeginTransaction(IsolationLevel isolationLevel)
5851
/// <inheritdoc/>
5952
public override void MakeSavepoint(string name)
6053
{
61-
EnsureIsNotDisposed();
62-
EnsureTransactionIsActive();
54+
var commandText = GetCreateSavepointCommandText(name);
55+
ExecuteNonQuery(commandText);
56+
}
6357

64-
string commandText = string.Format("SAVEPOINT {0}", name);
65-
using (DbCommand command = CreateCommand(commandText))
66-
command.ExecuteNonQuery();
58+
/// <inheritdoc/>
59+
public override Task MakeSavepointAsync(string name, CancellationToken token = default)
60+
{
61+
var commandText = GetCreateSavepointCommandText(name);
62+
return ExecuteNonQueryAsync(commandText, token);
6763
}
6864

6965
/// <inheritdoc/>
7066
public override void RollbackToSavepoint(string name)
7167
{
72-
EnsureIsNotDisposed();
73-
EnsureTransactionIsActive();
68+
var commandText = GetRollbackToSavepointCommandText(name);
69+
ExecuteNonQuery(commandText);
70+
}
7471

75-
string commandText = string.Format("ROLLBACK TO SAVEPOINT {0}; RELEASE SAVEPOINT {0};", name);
76-
using (DbCommand command = CreateCommand(commandText))
77-
command.ExecuteNonQuery();
72+
/// <inheritdoc/>
73+
public override Task RollbackToSavepointAsync(string name, CancellationToken token = default)
74+
{
75+
var commandText = GetRollbackToSavepointCommandText(name);
76+
return ExecuteNonQueryAsync(commandText, token);
7877
}
7978

8079
/// <inheritdoc/>
8180
public override void ReleaseSavepoint(string name)
8281
{
83-
EnsureIsNotDisposed();
84-
EnsureTransactionIsActive();
85-
86-
string commandText = string.Format("RELEASE SAVEPOINT {0}", name);
87-
using (DbCommand command = CreateCommand(commandText))
88-
command.ExecuteNonQuery();
82+
var commandText = GetReleaseSavepointCommandText(name);
83+
ExecuteNonQuery(commandText);
8984
}
9085

9186
/// <inheritdoc/>
92-
protected override void ClearActiveTransaction()
87+
public override Task ReleaseSavepointAsync(string name, CancellationToken token = default)
9388
{
94-
activeTransaction = null;
89+
var commandText = GetReleaseSavepointCommandText(name);
90+
return ExecuteNonQueryAsync(commandText, token);
9591
}
9692

9793
/// <inheritdoc/>
98-
protected override void ClearUnderlyingConnection()
94+
protected override void ClearActiveTransaction() => activeTransaction = null;
95+
96+
/// <inheritdoc/>
97+
protected override void ClearUnderlyingConnection() => underlyingConnection = null;
98+
99+
private static string GetCreateSavepointCommandText(string name) => $"SAVEPOINT {name}";
100+
101+
private static string GetRollbackToSavepointCommandText(string name) =>
102+
string.Format("ROLLBACK TO SAVEPOINT {0}; RELEASE SAVEPOINT {0};", name);
103+
104+
private static string GetReleaseSavepointCommandText(string name) => $"RELEASE SAVEPOINT {name}";
105+
106+
private void ExecuteNonQuery(string commandText)
99107
{
100-
underlyingConnection = null;
108+
EnsureIsNotDisposed();
109+
EnsureTransactionIsActive();
110+
111+
using var command = CreateCommand(commandText);
112+
command.ExecuteNonQuery();
113+
}
114+
115+
private async Task ExecuteNonQueryAsync(string commandText, CancellationToken token)
116+
{
117+
EnsureIsNotDisposed();
118+
EnsureTransactionIsActive();
119+
120+
var command = CreateCommand(commandText);
121+
await using (command.ConfigureAwait(false)) {
122+
await command.ExecuteNonQueryAsync(token).ConfigureAwait(false);
123+
}
101124
}
102125

103126
// Constructors

Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/Connection.cs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using Oracle.ManagedDataAccess.Client;
88
using System.Data;
99
using System.Data.Common;
10-
using Xtensive.Orm;
1110

1211
namespace Xtensive.Sql.Drivers.Oracle
1312
{
@@ -17,16 +16,13 @@ internal class Connection : SqlConnection
1716
private OracleTransaction activeTransaction;
1817

1918
/// <inheritdoc/>
20-
public override DbConnection UnderlyingConnection { get { return underlyingConnection; } }
19+
public override DbConnection UnderlyingConnection => underlyingConnection;
2120

2221
/// <inheritdoc/>
23-
public override DbTransaction ActiveTransaction { get { return activeTransaction; } }
22+
public override DbTransaction ActiveTransaction => activeTransaction;
2423

2524
/// <inheritdoc/>
26-
public override DbParameter CreateParameter()
27-
{
28-
return new OracleParameter();
29-
}
25+
public override DbParameter CreateParameter() => new OracleParameter();
3026

3127
/// <inheritdoc/>
3228
public override DbParameter CreateCursorParameter()
@@ -93,22 +89,14 @@ public override void ReleaseSavepoint(string name)
9389
}
9490

9591
/// <inheritdoc/>
96-
protected override void ClearActiveTransaction()
97-
{
98-
activeTransaction = null;
99-
}
92+
protected override void ClearActiveTransaction() => activeTransaction = null;
10093

10194
/// <inheritdoc/>
102-
protected override void ClearUnderlyingConnection()
103-
{
104-
underlyingConnection = null;
105-
}
95+
protected override void ClearUnderlyingConnection() => underlyingConnection = null;
10696

10797
/// <inheritdoc/>
108-
protected override DbCommand CreateNativeCommand()
109-
{
110-
return new OracleCommand {Connection = underlyingConnection, BindByName = true};
111-
}
98+
protected override DbCommand CreateNativeCommand() =>
99+
new OracleCommand {Connection = underlyingConnection, BindByName = true};
112100

113101
// Constructors
114102

0 commit comments

Comments
 (0)