Skip to content

Commit facb8c2

Browse files
Add an async enabled transaction synchronization (#1864)
Fixes #1752
1 parent d506d3c commit facb8c2

17 files changed

+568
-85
lines changed

src/NHibernate.Test/Async/NHSpecificTest/NH1082/Fixture.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99

1010

1111
using System;
12-
using NHibernate.Cfg;
1312
using NUnit.Framework;
14-
using Environment = NHibernate.Cfg.Environment;
1513

1614
namespace NHibernate.Test.NHSpecificTest.NH1082
1715
{
@@ -40,8 +38,31 @@ public async Task ExceptionsInBeforeTransactionCompletionAbortTransactionAsync()
4038
}
4139
}
4240

43-
4441
[Test]
42+
public async Task ExceptionsInTransactionSynchronizationBeforeTransactionCompletionAbortTransactionAsync()
43+
{
44+
var c = new C { ID = 1, Value = "value" };
45+
46+
var synchronization = new TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion();
47+
using (ISession s = Sfi.OpenSession())
48+
using (ITransaction t = s.BeginTransaction())
49+
{
50+
t.RegisterSynchronization(synchronization);
51+
52+
await (s.SaveAsync(c));
53+
54+
Assert.ThrowsAsync<BadException>(() => t.CommitAsync());
55+
}
56+
57+
using (ISession s = Sfi.OpenSession())
58+
{
59+
var objectInDb = await (s.GetAsync<C>(1));
60+
Assert.IsNull(objectInDb);
61+
}
62+
}
63+
64+
// Since v5.2
65+
[Test, Obsolete]
4566
public async Task ExceptionsInSynchronizationBeforeTransactionCompletionAbortTransactionAsync()
4667
{
4768
var c = new C { ID = 1, Value = "value" };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using NHibernate.Transaction;
12+
13+
namespace NHibernate.Test.NHSpecificTest.NH1082
14+
{
15+
using System.Threading.Tasks;
16+
using System.Threading;
17+
public partial class TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion : ITransactionCompletionSynchronization
18+
{
19+
public Task ExecuteBeforeTransactionCompletionAsync(CancellationToken cancellationToken)
20+
{
21+
throw new BadException();
22+
}
23+
24+
public Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationToken cancellationToken)
25+
{
26+
return Task.CompletedTask;
27+
}
28+
}
29+
}

src/NHibernate.Test/Async/TransactionTest/TransactionNotificationFixture.cs

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99

1010

1111
using System;
12-
using System.Collections;
12+
using System.Data;
1313
using System.Data.Common;
14+
using NHibernate.Transaction;
1415
using NUnit.Framework;
1516

1617
namespace NHibernate.Test.TransactionTest
@@ -20,22 +21,23 @@ namespace NHibernate.Test.TransactionTest
2021
[TestFixture]
2122
public class TransactionNotificationFixtureAsync : TestCase
2223
{
23-
protected override string[] Mappings
24-
{
25-
get { return Array.Empty<string>(); }
26-
}
24+
protected override string[] Mappings => Array.Empty<string>();
2725

2826
[Test]
2927
public async Task CommitAsync()
3028
{
3129
var interceptor = new RecordingInterceptor();
3230
using (var session = Sfi.WithOptions().Interceptor(interceptor).OpenSession())
31+
using (var tx = session.BeginTransaction())
3332
{
34-
ITransaction tx = session.BeginTransaction();
33+
var synchronisation = new Synchronization();
34+
tx.RegisterSynchronization(synchronisation);
3535
await (tx.CommitAsync());
36-
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1));
37-
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(1));
38-
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
36+
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1), "interceptor begin");
37+
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(1), "interceptor before");
38+
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor after");
39+
Assert.That(synchronisation.BeforeExecutions, Is.EqualTo(1), "sync before");
40+
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync after");
3941
}
4042
}
4143

@@ -44,26 +46,31 @@ public async Task RollbackAsync()
4446
{
4547
var interceptor = new RecordingInterceptor();
4648
using (var session = Sfi.WithOptions().Interceptor(interceptor).OpenSession())
49+
using (var tx = session.BeginTransaction())
4750
{
48-
ITransaction tx = session.BeginTransaction();
51+
var synchronisation = new Synchronization();
52+
tx.RegisterSynchronization(synchronisation);
4953
await (tx.RollbackAsync());
50-
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1));
51-
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(0));
52-
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
54+
Assert.That(interceptor.afterTransactionBeginCalled, Is.EqualTo(1), "interceptor begin");
55+
Assert.That(interceptor.beforeTransactionCompletionCalled, Is.EqualTo(0), "interceptor before");
56+
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor after");
57+
Assert.That(synchronisation.BeforeExecutions, Is.EqualTo(0), "sync before");
58+
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync after");
5359
}
5460
}
5561

56-
5762
[Theory]
5863
[Description("NH2128")]
5964
public async Task ShouldNotifyAfterTransactionAsync(bool usePrematureClose)
6065
{
6166
var interceptor = new RecordingInterceptor();
67+
var synchronisation = new Synchronization();
6268
ISession s;
6369

6470
using (s = OpenSession(interceptor))
65-
using (s.BeginTransaction())
71+
using (var t = s.BeginTransaction())
6672
{
73+
t.RegisterSynchronization(synchronisation);
6774
await (s.CreateCriteria<object>().ListAsync());
6875

6976
// Call session close while still inside transaction?
@@ -72,22 +79,24 @@ public async Task ShouldNotifyAfterTransactionAsync(bool usePrematureClose)
7279
}
7380

7481
Assert.That(s.IsOpen, Is.False);
75-
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
82+
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor");
83+
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync");
7684
}
7785

78-
7986
[Description("NH2128")]
8087
[Theory]
8188
public async Task ShouldNotifyAfterTransactionWithOwnConnectionAsync(bool usePrematureClose)
8289
{
8390
var interceptor = new RecordingInterceptor();
91+
var synchronisation = new Synchronization();
8492
ISession s;
8593

8694
using (var ownConnection = await (Sfi.ConnectionProvider.GetConnectionAsync(CancellationToken.None)))
8795
{
8896
using (s = Sfi.WithOptions().Connection(ownConnection).Interceptor(interceptor).OpenSession())
89-
using (s.BeginTransaction())
97+
using (var t = s.BeginTransaction())
9098
{
99+
t.RegisterSynchronization(synchronisation);
91100
await (s.CreateCriteria<object>().ListAsync());
92101

93102
// Call session close while still inside transaction?
@@ -97,7 +106,56 @@ public async Task ShouldNotifyAfterTransactionWithOwnConnectionAsync(bool usePre
97106
}
98107

99108
Assert.That(s.IsOpen, Is.False);
100-
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1));
109+
Assert.That(interceptor.afterTransactionCompletionCalled, Is.EqualTo(1), "interceptor");
110+
Assert.That(synchronisation.AfterExecutions, Is.EqualTo(1), "sync");
111+
}
112+
}
113+
114+
#region Synchronization classes
115+
116+
public partial class CustomTransaction : ITransaction
117+
{
118+
119+
public Task CommitAsync(CancellationToken cancellationToken = default(CancellationToken))
120+
{
121+
throw new NotImplementedException();
122+
}
123+
124+
public Task RollbackAsync(CancellationToken cancellationToken = default(CancellationToken))
125+
{
126+
throw new NotImplementedException();
127+
}
128+
}
129+
130+
public partial class Synchronization : ITransactionCompletionSynchronization
131+
{
132+
133+
public Task ExecuteBeforeTransactionCompletionAsync(CancellationToken cancellationToken)
134+
{
135+
try
136+
{
137+
BeforeExecutions += 1;
138+
return Task.CompletedTask;
139+
}
140+
catch (Exception ex)
141+
{
142+
return Task.FromException<object>(ex);
143+
}
144+
}
145+
146+
public Task ExecuteAfterTransactionCompletionAsync(bool success, CancellationToken cancellationToken)
147+
{
148+
try
149+
{
150+
AfterExecutions += 1;
151+
return Task.CompletedTask;
152+
}
153+
catch (Exception ex)
154+
{
155+
return Task.FromException<object>(ex);
156+
}
101157
}
102158
}
159+
160+
#endregion
103161
}

src/NHibernate.Test/NHSpecificTest/NH1082/Fixture.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
2-
using NHibernate.Cfg;
32
using NUnit.Framework;
4-
using Environment = NHibernate.Cfg.Environment;
53

64
namespace NHibernate.Test.NHSpecificTest.NH1082
75
{
@@ -29,8 +27,31 @@ public void ExceptionsInBeforeTransactionCompletionAbortTransaction()
2927
}
3028
}
3129

32-
3330
[Test]
31+
public void ExceptionsInTransactionSynchronizationBeforeTransactionCompletionAbortTransaction()
32+
{
33+
var c = new C { ID = 1, Value = "value" };
34+
35+
var synchronization = new TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion();
36+
using (ISession s = Sfi.OpenSession())
37+
using (ITransaction t = s.BeginTransaction())
38+
{
39+
t.RegisterSynchronization(synchronization);
40+
41+
s.Save(c);
42+
43+
Assert.Throws<BadException>(t.Commit);
44+
}
45+
46+
using (ISession s = Sfi.OpenSession())
47+
{
48+
var objectInDb = s.Get<C>(1);
49+
Assert.IsNull(objectInDb);
50+
}
51+
}
52+
53+
// Since v5.2
54+
[Test, Obsolete]
3455
public void ExceptionsInSynchronizationBeforeTransactionCompletionAbortTransaction()
3556
{
3657
var c = new C { ID = 1, Value = "value" };

src/NHibernate.Test/NHSpecificTest/NH1082/SynchronizationThatThrowsExceptionAtBeforeTransactionCompletion.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
using System;
12
using NHibernate.Transaction;
23

34
namespace NHibernate.Test.NHSpecificTest.NH1082
45
{
6+
// Since v5.2
7+
[Obsolete]
58
public class SynchronizationThatThrowsExceptionAtBeforeTransactionCompletion : ISynchronization
69
{
710
public void BeforeCompletion()
@@ -13,4 +16,4 @@ public void AfterCompletion(bool success)
1316
{
1417
}
1518
}
16-
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using NHibernate.Transaction;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH1082
4+
{
5+
public partial class TransactionSynchronizationThatThrowsExceptionAtBeforeTransactionCompletion : ITransactionCompletionSynchronization
6+
{
7+
public void ExecuteBeforeTransactionCompletion()
8+
{
9+
throw new BadException();
10+
}
11+
12+
public void ExecuteAfterTransactionCompletion(bool success)
13+
{
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)