Skip to content

Commit 75d2c9f

Browse files
NH-4018 - Testing manual join in distributed cases too.
1 parent 90a2bfe commit 75d2c9f

File tree

5 files changed

+153
-76
lines changed

5 files changed

+153
-76
lines changed

src/NHibernate.Test/Async/SystemTransactions/DistributedSystemTransactionFixture.cs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
using System.Transactions;
1515
using log4net;
1616
using log4net.Repository.Hierarchy;
17+
using NHibernate.Cfg;
18+
using NHibernate.Engine;
1719
using NHibernate.Linq;
1820
using NHibernate.Test.TransactionTest;
1921
using NUnit.Framework;
@@ -26,6 +28,7 @@ public class DistributedSystemTransactionFixtureAsync : SystemTransactionFixture
2628
{
2729
private static readonly ILog _log = LogManager.GetLogger(typeof(DistributedSystemTransactionFixtureAsync));
2830
protected override bool UseConnectionOnSystemTransactionPrepare => true;
31+
protected override bool AutoJoinTransaction => true;
2932

3033
protected override bool AppliesTo(Dialect.Dialect dialect)
3134
=> dialect.SupportsDistributedTransactions && base.AppliesTo(dialect);
@@ -434,6 +437,8 @@ public async Task CanUseSessionWithManyScopesAsync(bool explicitFlush)
434437
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
435438
{
436439
ForceEscalationToDistributedTx.Escalate();
440+
if (!AutoJoinTransaction)
441+
s.JoinTransaction();
437442
// Acquire the connection
438443
var count = await (s.Query<Person>().CountAsync());
439444
Assert.That(count, Is.EqualTo(0), "Unexpected initial entity count.");
@@ -442,6 +447,8 @@ public async Task CanUseSessionWithManyScopesAsync(bool explicitFlush)
442447
// No dodge here please! Allow to check chaining usages do not fail.
443448
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
444449
{
450+
if (!AutoJoinTransaction)
451+
s.JoinTransaction();
445452
await (s.SaveAsync(new Person()));
446453

447454
ForceEscalationToDistributedTx.Escalate();
@@ -457,12 +464,16 @@ public async Task CanUseSessionWithManyScopesAsync(bool explicitFlush)
457464
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
458465
{
459466
ForceEscalationToDistributedTx.Escalate();
467+
if (!AutoJoinTransaction)
468+
s.JoinTransaction();
460469
var count = await (s.Query<Person>().CountAsync());
461470
Assert.That(count, Is.EqualTo(1), "Unexpected entity count after committed insert.");
462471
tx.Complete();
463472
}
464473
using (new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
465474
{
475+
if (!AutoJoinTransaction)
476+
s.JoinTransaction();
466477
await (s.SaveAsync(new Person()));
467478

468479
ForceEscalationToDistributedTx.Escalate();
@@ -484,6 +495,8 @@ public async Task CanUseSessionWithManyScopesAsync(bool explicitFlush)
484495
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
485496
{
486497
ForceEscalationToDistributedTx.Escalate();
498+
if (!AutoJoinTransaction)
499+
s.JoinTransaction();
487500
var count = await (s.Query<Person>().CountAsync());
488501
Assert.That(count, Is.EqualTo(1), "Unexpected entity count after rollback-ed insert.");
489502
tx.Complete();
@@ -499,10 +512,12 @@ public async Task CanUseSessionOutsideOfScopeAfterScopeAsync(bool explicitFlush)
499512
// NpgsqlOperationInProgressException: The connection is already in state 'Executing'
500513
// Not much an issue since it is advised to not use ConnectionReleaseMode.OnClose.
501514
using (var s = OpenSession())
502-
//using (var s = Sfi.WithOptions().ConnectionReleaseMode(ConnectionReleaseMode.OnClose).OpenSession())
515+
//using (var s = WithOptions().ConnectionReleaseMode(ConnectionReleaseMode.OnClose).OpenSession())
503516
{
504517
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
505518
{
519+
if (!AutoJoinTransaction)
520+
s.JoinTransaction();
506521
await (s.SaveAsync(new Person()));
507522

508523
ForceEscalationToDistributedTx.Escalate();
@@ -582,7 +597,7 @@ public async Task WhenCommittingItemsAfterSessionDisposalWillAddThemTo2ndLevelCa
582597
const string notNullData = "test";
583598
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
584599
{
585-
using (var s = Sfi.OpenSession())
600+
using (var s = OpenSession())
586601
{
587602
var person = new CacheablePerson { NotNullData = notNullData };
588603
await (s.SaveAsync(person));
@@ -617,7 +632,7 @@ public async Task WhenCommittingItemsAfterSessionDisposalWillAddThemTo2ndLevelCa
617632
// entity to load, allowing the session to not use the connection at all.
618633
// Will fail if a transaction manager tries to enlist user supplied connection. Do
619634
// not add a transaction scope below.
620-
using (var s = Sfi.WithOptions().Connection(connection).OpenSession())
635+
using (var s = WithOptions().Connection(connection).OpenSession())
621636
{
622637
CacheablePerson person = null;
623638
Assert.DoesNotThrowAsync(async () => person = await (s.LoadAsync<CacheablePerson>(id)), "Failed loading entity from second level cache.");
@@ -633,6 +648,8 @@ public async Task DoNotDeadlockOnAfterTransactionWaitAsync()
633648
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
634649
{
635650
ForceEscalationToDistributedTx.Escalate();
651+
if (!AutoJoinTransaction)
652+
s.JoinTransaction();
636653
await (s.SaveAsync(new Person()));
637654

638655
await (s.FlushAsync());
@@ -651,6 +668,8 @@ public async Task EnforceConnectionUsageRulesOnTransactionCompletionAsync()
651668
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
652669
{
653670
ForceEscalationToDistributedTx.Escalate();
671+
if (!AutoJoinTransaction)
672+
s.JoinTransaction();
654673
await (s.SaveAsync(new Person()));
655674

656675
await (s.FlushAsync());
@@ -732,4 +751,19 @@ public class DistributedSystemTransactionWithoutConnectionFromPrepareFixtureAsyn
732751
{
733752
protected override bool UseConnectionOnSystemTransactionPrepare => false;
734753
}
754+
755+
[TestFixture]
756+
public class DistributedSystemTransactionWithoutAutoJoinTransactionAsync : DistributedSystemTransactionFixtureAsync
757+
{
758+
protected override bool AutoJoinTransaction => false;
759+
760+
protected override void Configure(Configuration configuration)
761+
{
762+
base.Configure(configuration);
763+
DisableConnectionAutoEnlist(configuration);
764+
}
765+
766+
protected override bool AppliesTo(ISessionFactoryImplementor factory)
767+
=> base.AppliesTo(factory) && factory.ConnectionProvider.Driver.SupportsEnlistmentWhenAutoEnlistmentIsDisabled;
768+
}
735769
}

src/NHibernate.Test/Async/SystemTransactions/SystemTransactionFixture.cs

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,12 @@
1111
using System;
1212
using System.Collections.Generic;
1313
using System.Linq;
14-
using System.Text.RegularExpressions;
1514
using System.Threading;
1615
using System.Transactions;
1716
using NHibernate.Cfg;
18-
using NHibernate.Driver;
1917
using NHibernate.Engine;
2018
using NHibernate.Linq;
2119
using NHibernate.Test.TransactionTest;
22-
using NHibernate.Util;
2320
using NUnit.Framework;
2421

2522
namespace NHibernate.Test.SystemTransactions
@@ -29,7 +26,7 @@ namespace NHibernate.Test.SystemTransactions
2926
public class SystemTransactionFixtureAsync : SystemTransactionFixtureBase
3027
{
3128
protected override bool UseConnectionOnSystemTransactionPrepare => true;
32-
protected virtual bool AutoJoinTransaction => true;
29+
protected override bool AutoJoinTransaction => true;
3330

3431
[Test]
3532
public async Task WillNotCrashOnPrepareFailureAsync()
@@ -506,22 +503,6 @@ public async Task EnforceConnectionUsageRulesOnTransactionCompletionAsync()
506503
// Currently always forbidden, whatever UseConnectionOnSystemTransactionEvents.
507504
Assert.That(interceptor.AfterException, Is.TypeOf<HibernateException>());
508505
}
509-
510-
protected override ISession OpenSession()
511-
{
512-
if (AutoJoinTransaction)
513-
return base.OpenSession();
514-
515-
var session = Sfi.WithOptions().AutoJoinTransaction(false).OpenSession();
516-
if (System.Transactions.Transaction.Current != null)
517-
session.JoinTransaction();
518-
return session;
519-
}
520-
521-
protected ISessionBuilder WithOptions()
522-
{
523-
return Sfi.WithOptions().AutoJoinTransaction(AutoJoinTransaction);
524-
}
525506
}
526507

527508
[TestFixture]
@@ -535,21 +516,8 @@ public class SystemTransactionWithoutConnectionAutoEnlistmentFixtureAsync : Syst
535516
{
536517
protected override void Configure(Configuration configuration)
537518
{
538-
var connectionString = configuration.GetProperty(Cfg.Environment.ConnectionString);
539-
var autoEnlistmentKeyword = "Enlist";
540-
var autoEnlistmentKeywordPattern = autoEnlistmentKeyword;
541-
if (configuration.GetDerivedProperties().TryGetValue(Cfg.Environment.ConnectionDriver, out var driver) &&
542-
typeof(MySqlDataDriver).IsAssignableFrom(ReflectHelper.ClassForName(driver)))
543-
{
544-
autoEnlistmentKeyword = "AutoEnlist";
545-
autoEnlistmentKeywordPattern = "Auto ?Enlist";
546-
}
547-
// Purge any previous enlist
548-
connectionString = Regex.Replace(
549-
connectionString, $"[^;\"a-zA-Z]*{autoEnlistmentKeywordPattern}=[^;\"]*", string.Empty,
550-
RegexOptions.IgnoreCase | RegexOptions.Multiline);
551-
connectionString += $";{autoEnlistmentKeyword}=false;";
552-
configuration.SetProperty(Cfg.Environment.ConnectionString, connectionString);
519+
base.Configure(configuration);
520+
DisableConnectionAutoEnlist(configuration);
553521
}
554522

555523
protected override bool AppliesTo(ISessionFactoryImplementor factory)

src/NHibernate.Test/SystemTransactions/DistributedSystemTransactionFixture.cs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using System.Transactions;
55
using log4net;
66
using log4net.Repository.Hierarchy;
7+
using NHibernate.Cfg;
8+
using NHibernate.Engine;
79
using NHibernate.Linq;
810
using NHibernate.Test.TransactionTest;
911
using NUnit.Framework;
@@ -15,6 +17,7 @@ public class DistributedSystemTransactionFixture : SystemTransactionFixtureBase
1517
{
1618
private static readonly ILog _log = LogManager.GetLogger(typeof(DistributedSystemTransactionFixture));
1719
protected override bool UseConnectionOnSystemTransactionPrepare => true;
20+
protected override bool AutoJoinTransaction => true;
1821

1922
protected override bool AppliesTo(Dialect.Dialect dialect)
2023
=> dialect.SupportsDistributedTransactions && base.AppliesTo(dialect);
@@ -463,6 +466,8 @@ public void CanUseSessionWithManyScopes(bool explicitFlush)
463466
using (var tx = new TransactionScope())
464467
{
465468
ForceEscalationToDistributedTx.Escalate();
469+
if (!AutoJoinTransaction)
470+
s.JoinTransaction();
466471
// Acquire the connection
467472
var count = s.Query<Person>().Count();
468473
Assert.That(count, Is.EqualTo(0), "Unexpected initial entity count.");
@@ -471,6 +476,8 @@ public void CanUseSessionWithManyScopes(bool explicitFlush)
471476
// No dodge here please! Allow to check chaining usages do not fail.
472477
using (var tx = new TransactionScope())
473478
{
479+
if (!AutoJoinTransaction)
480+
s.JoinTransaction();
474481
s.Save(new Person());
475482

476483
ForceEscalationToDistributedTx.Escalate();
@@ -486,12 +493,16 @@ public void CanUseSessionWithManyScopes(bool explicitFlush)
486493
using (var tx = new TransactionScope())
487494
{
488495
ForceEscalationToDistributedTx.Escalate();
496+
if (!AutoJoinTransaction)
497+
s.JoinTransaction();
489498
var count = s.Query<Person>().Count();
490499
Assert.That(count, Is.EqualTo(1), "Unexpected entity count after committed insert.");
491500
tx.Complete();
492501
}
493502
using (new TransactionScope())
494503
{
504+
if (!AutoJoinTransaction)
505+
s.JoinTransaction();
495506
s.Save(new Person());
496507

497508
ForceEscalationToDistributedTx.Escalate();
@@ -513,6 +524,8 @@ public void CanUseSessionWithManyScopes(bool explicitFlush)
513524
using (var tx = new TransactionScope())
514525
{
515526
ForceEscalationToDistributedTx.Escalate();
527+
if (!AutoJoinTransaction)
528+
s.JoinTransaction();
516529
var count = s.Query<Person>().Count();
517530
Assert.That(count, Is.EqualTo(1), "Unexpected entity count after rollback-ed insert.");
518531
tx.Complete();
@@ -528,10 +541,12 @@ public void CanUseSessionOutsideOfScopeAfterScope(bool explicitFlush)
528541
// NpgsqlOperationInProgressException: The connection is already in state 'Executing'
529542
// Not much an issue since it is advised to not use ConnectionReleaseMode.OnClose.
530543
using (var s = OpenSession())
531-
//using (var s = Sfi.WithOptions().ConnectionReleaseMode(ConnectionReleaseMode.OnClose).OpenSession())
544+
//using (var s = WithOptions().ConnectionReleaseMode(ConnectionReleaseMode.OnClose).OpenSession())
532545
{
533546
using (var tx = new TransactionScope())
534547
{
548+
if (!AutoJoinTransaction)
549+
s.JoinTransaction();
535550
s.Save(new Person());
536551

537552
ForceEscalationToDistributedTx.Escalate();
@@ -611,7 +626,7 @@ public void WhenCommittingItemsAfterSessionDisposalWillAddThemTo2ndLevelCache()
611626
const string notNullData = "test";
612627
using (var tx = new TransactionScope())
613628
{
614-
using (var s = Sfi.OpenSession())
629+
using (var s = OpenSession())
615630
{
616631
var person = new CacheablePerson { NotNullData = notNullData };
617632
s.Save(person);
@@ -646,7 +661,7 @@ public void WhenCommittingItemsAfterSessionDisposalWillAddThemTo2ndLevelCache()
646661
// entity to load, allowing the session to not use the connection at all.
647662
// Will fail if a transaction manager tries to enlist user supplied connection. Do
648663
// not add a transaction scope below.
649-
using (var s = Sfi.WithOptions().Connection(connection).OpenSession())
664+
using (var s = WithOptions().Connection(connection).OpenSession())
650665
{
651666
CacheablePerson person = null;
652667
Assert.DoesNotThrow(() => person = s.Load<CacheablePerson>(id), "Failed loading entity from second level cache.");
@@ -662,6 +677,8 @@ public void DoNotDeadlockOnAfterTransactionWait()
662677
using (var tx = new TransactionScope())
663678
{
664679
ForceEscalationToDistributedTx.Escalate();
680+
if (!AutoJoinTransaction)
681+
s.JoinTransaction();
665682
s.Save(new Person());
666683

667684
s.Flush();
@@ -680,6 +697,8 @@ public void EnforceConnectionUsageRulesOnTransactionCompletion()
680697
using (var tx = new TransactionScope())
681698
{
682699
ForceEscalationToDistributedTx.Escalate();
700+
if (!AutoJoinTransaction)
701+
s.JoinTransaction();
683702
s.Save(new Person());
684703

685704
s.Flush();
@@ -698,6 +717,17 @@ public void EnforceConnectionUsageRulesOnTransactionCompletion()
698717
Assert.That(interceptor.AfterException, Is.TypeOf<HibernateException>());
699718
}
700719

720+
[Test]
721+
public void AdditionalJoinDoesNotThrow()
722+
{
723+
using (new TransactionScope())
724+
using (var s = OpenSession())
725+
{
726+
ForceEscalationToDistributedTx.Escalate();
727+
Assert.DoesNotThrow(() => s.JoinTransaction());
728+
}
729+
}
730+
701731
private void DodgeTransactionCompletionDelayIfRequired()
702732
{
703733
if (Sfi.ConnectionProvider.Driver.HasDelayedDistributedTransactionCompletion)
@@ -761,4 +791,33 @@ public class DistributedSystemTransactionWithoutConnectionFromPrepareFixture : D
761791
{
762792
protected override bool UseConnectionOnSystemTransactionPrepare => false;
763793
}
794+
795+
[TestFixture]
796+
public class DistributedSystemTransactionWithoutAutoJoinTransaction : DistributedSystemTransactionFixture
797+
{
798+
protected override bool AutoJoinTransaction => false;
799+
800+
protected override void Configure(Configuration configuration)
801+
{
802+
base.Configure(configuration);
803+
DisableConnectionAutoEnlist(configuration);
804+
}
805+
806+
protected override bool AppliesTo(ISessionFactoryImplementor factory)
807+
=> base.AppliesTo(factory) && factory.ConnectionProvider.Driver.SupportsEnlistmentWhenAutoEnlistmentIsDisabled;
808+
809+
[Test]
810+
public void SessionIsNotEnlisted()
811+
{
812+
using (new TransactionScope())
813+
{
814+
ForceEscalationToDistributedTx.Escalate();
815+
// Dodge the OpenSession override which call JoinTransaction by calling WithOptions().
816+
using (var s = WithOptions().OpenSession())
817+
{
818+
Assert.That(s.GetSessionImplementation().TransactionContext, Is.Null);
819+
}
820+
}
821+
}
822+
}
764823
}

0 commit comments

Comments
 (0)