Skip to content

Commit 2e2b42a

Browse files
committed
Make OpenTransaction method async
1 parent 8e0b67b commit 2e2b42a

8 files changed

Lines changed: 376 additions & 135 deletions

File tree

Orm/Xtensive.Orm/Orm/Providers/ChainingSessionHandler.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,28 @@ public override ValueTask RollbackTransactionAsync(Transaction transaction) =>
6464
ChainedHandler.RollbackTransactionAsync(transaction);
6565

6666
/// <inheritdoc/>
67-
public override void CreateSavepoint(Transaction transaction)
68-
{
67+
public override void CreateSavepoint(Transaction transaction) =>
6968
ChainedHandler.CreateSavepoint(transaction);
70-
}
7169

7270
/// <inheritdoc/>
73-
public override void RollbackToSavepoint(Transaction transaction)
74-
{
71+
public override ValueTask CreateSavepointAsync(Transaction transaction, CancellationToken token = default) =>
72+
ChainedHandler.CreateSavepointAsync(transaction, token);
73+
74+
/// <inheritdoc/>
75+
public override void RollbackToSavepoint(Transaction transaction) =>
7576
ChainedHandler.RollbackToSavepoint(transaction);
76-
}
7777

7878
/// <inheritdoc/>
79-
public override void ReleaseSavepoint(Transaction transaction)
80-
{
79+
public override ValueTask RollbackToSavepointAsync(Transaction transaction, CancellationToken token = default) =>
80+
ChainedHandler.RollbackToSavepointAsync(transaction, token);
81+
82+
/// <inheritdoc/>
83+
public override void ReleaseSavepoint(Transaction transaction) =>
8184
ChainedHandler.ReleaseSavepoint(transaction);
82-
}
85+
86+
/// <inheritdoc/>
87+
public override ValueTask ReleaseSavepointAsync(Transaction transaction, CancellationToken token = default) =>
88+
ChainedHandler.ReleaseSavepointAsync(transaction, token);
8389

8490
/// <inheritdoc/>
8591
public override void ExecuteQueryTasks(IEnumerable<QueryTask> queryTasks, bool allowPartialExecution)

Orm/Xtensive.Orm/Orm/Providers/SessionHandler.Transactions.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
// Created by: Denis Krjuchkov
55
// Created: 2009.08.19
66

7-
using System;
7+
using System.Threading;
88
using System.Threading.Tasks;
9-
using Xtensive.Orm;
109

1110

1211
namespace Xtensive.Orm.Providers
@@ -71,14 +70,41 @@ public virtual ValueTask RollbackTransactionAsync(Transaction transaction)
7170
/// </summary>
7271
public abstract void CreateSavepoint(Transaction transaction);
7372

73+
/// <summary>
74+
/// Asynchronously creates the savepoint.
75+
/// </summary>
76+
public virtual ValueTask CreateSavepointAsync(Transaction transaction, CancellationToken token = default)
77+
{
78+
CreateSavepoint(transaction);
79+
return default;
80+
}
81+
7482
/// <summary>
7583
/// Releases the savepoint.
7684
/// </summary>
7785
public abstract void ReleaseSavepoint(Transaction transaction);
7886

7987
/// <summary>
80-
/// Rollbacks to savepoint.
88+
/// Asynchronously releases the savepoint.
89+
/// </summary>
90+
public virtual ValueTask ReleaseSavepointAsync(Transaction transaction, CancellationToken token = default)
91+
{
92+
ReleaseSavepoint(transaction);
93+
return default;
94+
}
95+
96+
/// <summary>
97+
/// Rolls backs to the savepoint.
8198
/// </summary>
8299
public abstract void RollbackToSavepoint(Transaction transaction);
100+
101+
/// <summary>
102+
/// Asynchronously rolls backs to the savepoint.
103+
/// </summary>
104+
public virtual ValueTask RollbackToSavepointAsync(Transaction transaction, CancellationToken token = default)
105+
{
106+
RollbackToSavepoint(transaction);
107+
return default;
108+
}
83109
}
84110
}

Orm/Xtensive.Orm/Orm/Providers/SqlSessionHandler.cs

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,21 @@ public override void BeginTransaction(Transaction transaction)
8484
public override void CommitTransaction(Transaction transaction)
8585
{
8686
pendingTransaction = null;
87-
if (connection.ActiveTransaction!=null && !transactionIsExternal)
87+
if (connection.ActiveTransaction != null && !transactionIsExternal) {
8888
driver.CommitTransaction(Session, connection);
89-
if (!connectionIsExternal)
89+
}
90+
91+
if (!connectionIsExternal) {
9092
driver.CloseConnection(Session, connection);
93+
}
9194
}
9295

9396
/// <inheritdoc/>
9497
public override async ValueTask CommitTransactionAsync(Transaction transaction)
9598
{
9699
pendingTransaction = null;
97-
if (connection.ActiveTransaction!=null && !transactionIsExternal) {
98-
driver.CommitTransaction(Session, connection);
100+
if (connection.ActiveTransaction != null && !transactionIsExternal) {
101+
await driver.CommitTransactionAsync(Session, connection).ConfigureAwait(false);
99102
}
100103

101104
if (!connectionIsExternal) {
@@ -107,18 +110,21 @@ public override async ValueTask CommitTransactionAsync(Transaction transaction)
107110
public override void RollbackTransaction(Transaction transaction)
108111
{
109112
pendingTransaction = null;
110-
if (connection.ActiveTransaction!=null && !transactionIsExternal)
113+
if (connection.ActiveTransaction != null && !transactionIsExternal) {
111114
driver.RollbackTransaction(Session, connection);
112-
if (!connectionIsExternal)
115+
}
116+
117+
if (!connectionIsExternal) {
113118
driver.CloseConnection(Session, connection);
119+
}
114120
}
115121

116122
/// <inheritdoc/>
117123
public override async ValueTask RollbackTransactionAsync(Transaction transaction)
118124
{
119125
pendingTransaction = null;
120-
if (connection.ActiveTransaction!=null && !transactionIsExternal) {
121-
driver.RollbackTransaction(Session, connection);
126+
if (connection.ActiveTransaction != null && !transactionIsExternal) {
127+
await driver.RollbackTransactionAsync(Session, connection).ConfigureAwait(false);
122128
}
123129

124130
if (!connectionIsExternal) {
@@ -133,20 +139,41 @@ public override void CreateSavepoint(Transaction transaction)
133139
driver.MakeSavepoint(Session, connection, transaction.SavepointName);
134140
}
135141

142+
/// <inheritdoc/>
143+
public override async ValueTask CreateSavepointAsync(Transaction transaction, CancellationToken token = default)
144+
{
145+
await PrepareAsync(token).ConfigureAwait(false);
146+
await driver.MakeSavepointAsync(Session, connection, transaction.SavepointName, token).ConfigureAwait(false);
147+
}
148+
136149
/// <inheritdoc/>
137150
public override void RollbackToSavepoint(Transaction transaction)
138151
{
139152
Prepare();
140153
driver.RollbackToSavepoint(Session, connection, transaction.SavepointName);
141154
}
142155

156+
/// <inheritdoc/>
157+
public override async ValueTask RollbackToSavepointAsync(Transaction transaction, CancellationToken token = default)
158+
{
159+
await PrepareAsync(token).ConfigureAwait(false);
160+
await driver.RollbackToSavepointAsync(Session, connection, transaction.SavepointName, token).ConfigureAwait(false);
161+
}
162+
143163
/// <inheritdoc/>
144164
public override void ReleaseSavepoint(Transaction transaction)
145165
{
146166
Prepare();
147167
driver.ReleaseSavepoint(Session, connection, transaction.SavepointName);
148168
}
149169

170+
/// <inheritdoc/>
171+
public override async ValueTask ReleaseSavepointAsync(Transaction transaction, CancellationToken token = default)
172+
{
173+
await PrepareAsync(token).ConfigureAwait(false);
174+
await driver.ReleaseSavepointAsync(Session, connection, transaction.SavepointName, token).ConfigureAwait(false);
175+
}
176+
150177
/// <inheritdoc/>
151178
public override void CompletingTransaction(Transaction transaction)
152179
{
@@ -173,16 +200,23 @@ private void Prepare()
173200
{
174201
Session.EnsureNotDisposed();
175202
driver.EnsureConnectionIsOpen(Session, connection);
176-
foreach (var script in initializationSqlScripts)
177-
using (var command = connection.CreateCommand(script))
203+
foreach (var script in initializationSqlScripts) {
204+
using (var command = connection.CreateCommand(script)) {
178205
driver.ExecuteNonQuery(Session, command);
206+
}
207+
}
208+
179209
initializationSqlScripts.Clear();
180-
if (pendingTransaction==null)
210+
if (pendingTransaction==null) {
181211
return;
212+
}
213+
182214
var transaction = pendingTransaction;
183215
pendingTransaction = null;
184-
if (connection.ActiveTransaction==null) // Handle external transactions
216+
if (connection.ActiveTransaction==null) {
217+
// Handle external transactions
185218
driver.BeginTransaction(Session, connection, IsolationLevelConverter.Convert(transaction.IsolationLevel));
219+
}
186220
}
187221

188222
private async Task PrepareAsync(CancellationToken cancellationToken)
@@ -202,14 +236,16 @@ private async Task PrepareAsync(CancellationToken cancellationToken)
202236
throw;
203237
}
204238

205-
if (pendingTransaction==null) {
239+
if (pendingTransaction == null) {
206240
return;
207241
}
208242

209243
var transaction = pendingTransaction;
210244
pendingTransaction = null;
211-
if (connection.ActiveTransaction==null) { // Handle external transactions
212-
driver.BeginTransaction(Session, connection, IsolationLevelConverter.Convert(transaction.IsolationLevel));
245+
if (connection.ActiveTransaction == null) {
246+
// Handle external transactions
247+
var isolationLevel = IsolationLevelConverter.Convert(transaction.IsolationLevel);
248+
await driver.BeginTransactionAsync(Session, connection, isolationLevel, cancellationToken).ConfigureAwait(false);
213249
}
214250
}
215251

Orm/Xtensive.Orm/Orm/Session.Persist.cs

Lines changed: 74 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,13 @@ internal async Task PersistAsync(PersistReason reason, CancellationToken token =
113113
private async ValueTask Persist(PersistReason reason, bool isAsync, CancellationToken token = default)
114114
{
115115
EnsureNotDisposed();
116-
if (IsPersisting || EntityChangeRegistry.Count==0) {
116+
if (IsPersisting || EntityChangeRegistry.Count == 0) {
117117
return;
118118
}
119119

120120
var performPinning = pinner.RootCount > 0;
121-
if (performPinning || (disableAutoSaveChanges && !Configuration.Supports(SessionOptions.NonTransactionalEntityStates))) {
121+
if (performPinning
122+
|| (disableAutoSaveChanges && !Configuration.Supports(SessionOptions.NonTransactionalEntityStates))) {
122123
switch (reason) {
123124
case PersistReason.NestedTransaction:
124125
case PersistReason.Commit:
@@ -130,76 +131,93 @@ private async ValueTask Persist(PersistReason reason, bool isAsync, Cancellation
130131
return;
131132
}
132133

133-
using (var ts = OpenTransaction(TransactionOpenMode.Default, IsolationLevel.Unspecified, false)) {
134+
var ts = await InnerOpenTransaction(
135+
TransactionOpenMode.Default, IsolationLevel.Unspecified, false, isAsync, token);
136+
try {
134137
IsPersisting = true;
135138
persistingIsFailed = false;
136139
SystemEvents.NotifyPersisting();
137140
Events.NotifyPersisting();
138-
try {
139-
using (this.OpenSystemLogicOnlyRegion()) {
140-
DemandTransaction();
141-
if (IsDebugEventLoggingEnabled) {
142-
OrmLog.Debug(Strings.LogSessionXPersistingReasonY, this, reason);
143-
}
141+
using (OpenSystemLogicOnlyRegion()) {
142+
DemandTransaction();
143+
if (IsDebugEventLoggingEnabled) {
144+
OrmLog.Debug(Strings.LogSessionXPersistingReasonY, this, reason);
145+
}
146+
147+
EntityChangeRegistry itemsToPersist;
148+
if (performPinning) {
149+
pinner.Process(EntityChangeRegistry);
150+
itemsToPersist = pinner.PersistableItems;
151+
}
152+
else {
153+
itemsToPersist = EntityChangeRegistry;
154+
}
144155

145-
EntityChangeRegistry itemsToPersist;
146-
if (performPinning) {
147-
pinner.Process(EntityChangeRegistry);
148-
itemsToPersist = pinner.PersistableItems;
156+
if (LazyKeyGenerationIsEnabled) {
157+
await RemapEntityKeys(remapper.Remap(itemsToPersist), isAsync, token).ConfigureAwait(false);
158+
}
159+
160+
ApplyEntitySetsChanges();
161+
var persistIsSuccessful = false;
162+
try {
163+
if (isAsync) {
164+
await Handler.PersistAsync(itemsToPersist, reason == PersistReason.Query, token).ConfigureAwait(false);
149165
}
150166
else {
151-
itemsToPersist = EntityChangeRegistry;
167+
Handler.Persist(itemsToPersist, reason == PersistReason.Query);
152168
}
153169

154-
if (LazyKeyGenerationIsEnabled) {
155-
await RemapEntityKeys(remapper.Remap(itemsToPersist), isAsync, token).ConfigureAwait(false);
156-
}
157-
ApplyEntitySetsChanges();
158-
var persistIsSuccessful = false;
159-
try {
160-
if (isAsync) {
161-
await Handler.PersistAsync(itemsToPersist, reason == PersistReason.Query, token).ConfigureAwait(false);
170+
persistIsSuccessful = true;
171+
}
172+
catch (Exception) {
173+
persistingIsFailed = true;
174+
RollbackChangesOfEntitySets();
175+
RestoreEntityChangesAfterPersistFailed();
176+
throw;
177+
}
178+
finally {
179+
if (persistIsSuccessful || !Configuration.Supports(SessionOptions.NonTransactionalEntityStates)) {
180+
DropDifferenceBackup();
181+
foreach (var item in itemsToPersist.GetItems(PersistenceState.New)) {
182+
item.PersistenceState = PersistenceState.Synchronized;
162183
}
163-
else {
164-
Handler.Persist(itemsToPersist, reason == PersistReason.Query);
184+
185+
foreach (var item in itemsToPersist.GetItems(PersistenceState.Modified)) {
186+
item.PersistenceState = PersistenceState.Synchronized;
165187
}
166-
persistIsSuccessful = true;
167-
}
168-
catch(Exception) {
169-
persistingIsFailed = true;
170-
RollbackChangesOfEntitySets();
171-
RestoreEntityChangesAfterPersistFailed();
172-
throw;
173-
}
174-
finally {
175-
if (persistIsSuccessful || !Configuration.Supports(SessionOptions.NonTransactionalEntityStates)) {
176-
DropDifferenceBackup();
177-
foreach (var item in itemsToPersist.GetItems(PersistenceState.New))
178-
item.PersistenceState = PersistenceState.Synchronized;
179-
foreach (var item in itemsToPersist.GetItems(PersistenceState.Modified))
180-
item.PersistenceState = PersistenceState.Synchronized;
181-
foreach (var item in itemsToPersist.GetItems(PersistenceState.Removed))
182-
item.Update(null);
183-
184-
if (performPinning) {
185-
EntityChangeRegistry = pinner.PinnedItems;
186-
pinner.Reset();
187-
}
188-
else
189-
EntityChangeRegistry.Clear();
190-
EntitySetChangeRegistry.Clear();
191-
NonPairedReferencesRegistry.Clear();
188+
189+
foreach (var item in itemsToPersist.GetItems(PersistenceState.Removed)) {
190+
item.Update(null);
192191
}
193-
if (IsDebugEventLoggingEnabled) {
194-
OrmLog.Debug(Strings.LogSessionXPersistCompleted, this);
192+
193+
if (performPinning) {
194+
EntityChangeRegistry = pinner.PinnedItems;
195+
pinner.Reset();
195196
}
197+
else {
198+
EntityChangeRegistry.Clear();
199+
}
200+
201+
EntitySetChangeRegistry.Clear();
202+
NonPairedReferencesRegistry.Clear();
203+
}
204+
205+
if (IsDebugEventLoggingEnabled) {
206+
OrmLog.Debug(Strings.LogSessionXPersistCompleted, this);
196207
}
197208
}
198-
SystemEvents.NotifyPersisted();
199-
Events.NotifyPersisted();
200209
}
201-
finally {
202-
IsPersisting = false;
210+
211+
SystemEvents.NotifyPersisted();
212+
Events.NotifyPersisted();
213+
}
214+
finally {
215+
IsPersisting = false;
216+
if (isAsync) {
217+
await ts.DisposeAsync().ConfigureAwait(false);
218+
}
219+
else {
220+
ts.Dispose();
203221
}
204222
}
205223
}

0 commit comments

Comments
 (0)