4
4
using System . Threading ;
5
5
using System . Transactions ;
6
6
using NHibernate . Cfg ;
7
+ using NHibernate . Driver ;
7
8
using NHibernate . Engine ;
8
- using NHibernate . Linq ;
9
9
using NHibernate . Test . TransactionTest ;
10
10
using NUnit . Framework ;
11
11
@@ -502,6 +502,120 @@ public void AdditionalJoinDoesNotThrow()
502
502
Assert . DoesNotThrow ( ( ) => s . JoinTransaction ( ) ) ;
503
503
}
504
504
}
505
+
506
+ [ Theory ]
507
+ public void CanUseDependentTransaction ( bool explicitFlush )
508
+ {
509
+ if ( ! TestDialect . SupportsDependentTransaction )
510
+ Assert . Ignore ( "Dialect does not support dependent transactions" ) ;
511
+ IgnoreIfUnsupported ( explicitFlush ) ;
512
+
513
+ try
514
+ {
515
+ using ( var committable = new CommittableTransaction ( ) )
516
+ {
517
+ System . Transactions . Transaction . Current = committable ;
518
+ using ( var clone = committable . DependentClone ( DependentCloneOption . RollbackIfNotComplete ) )
519
+ {
520
+ System . Transactions . Transaction . Current = clone ;
521
+
522
+ using ( var s = OpenSession ( ) )
523
+ {
524
+ if ( ! AutoJoinTransaction )
525
+ s . JoinTransaction ( ) ;
526
+ s . Save ( new Person ( ) ) ;
527
+
528
+ if ( explicitFlush )
529
+ s . Flush ( ) ;
530
+ clone . Complete ( ) ;
531
+ }
532
+ }
533
+
534
+ System . Transactions . Transaction . Current = committable ;
535
+ committable . Commit ( ) ;
536
+ }
537
+ }
538
+ finally
539
+ {
540
+ System . Transactions . Transaction . Current = null ;
541
+ }
542
+ }
543
+
544
+ [ Theory ]
545
+ public void CanUseSessionWithManyDependentTransaction ( bool explicitFlush )
546
+ {
547
+ if ( ! TestDialect . SupportsDependentTransaction )
548
+ Assert . Ignore ( "Dialect does not support dependent transactions" ) ;
549
+ IgnoreIfUnsupported ( explicitFlush ) ;
550
+ // ODBC with SQL-Server always causes system transactions to go distributed, which causes their transaction completion to run
551
+ // asynchronously. But ODBC enlistment also check the previous transaction in a way that do not guard against it
552
+ // being concurrently disposed of. See https://github.com/nhibernate/nhibernate-core/pull/1505 for more details.
553
+ if ( Sfi . ConnectionProvider . Driver is OdbcDriver )
554
+ Assert . Ignore ( "ODBC sometimes fails on second scope by checking the previous transaction status, which may yield an object disposed exception" ) ;
555
+
556
+ try
557
+ {
558
+ using ( var s = WithOptions ( ) . ConnectionReleaseMode ( ConnectionReleaseMode . OnClose ) . OpenSession ( ) )
559
+ {
560
+ using ( var committable = new CommittableTransaction ( ) )
561
+ {
562
+ System . Transactions . Transaction . Current = committable ;
563
+ using ( var clone = committable . DependentClone ( DependentCloneOption . RollbackIfNotComplete ) )
564
+ {
565
+ System . Transactions . Transaction . Current = clone ;
566
+ if ( ! AutoJoinTransaction )
567
+ s . JoinTransaction ( ) ;
568
+ // Acquire the connection
569
+ var count = s . Query < Person > ( ) . Count ( ) ;
570
+ Assert . That ( count , Is . EqualTo ( 0 ) , "Unexpected initial entity count." ) ;
571
+ clone . Complete ( ) ;
572
+ }
573
+
574
+ using ( var clone = committable . DependentClone ( DependentCloneOption . RollbackIfNotComplete ) )
575
+ {
576
+ System . Transactions . Transaction . Current = clone ;
577
+ if ( ! AutoJoinTransaction )
578
+ s . JoinTransaction ( ) ;
579
+ s . Save ( new Person ( ) ) ;
580
+
581
+ if ( explicitFlush )
582
+ s . Flush ( ) ;
583
+
584
+ clone . Complete ( ) ;
585
+ }
586
+
587
+ using ( var clone = committable . DependentClone ( DependentCloneOption . RollbackIfNotComplete ) )
588
+ {
589
+ System . Transactions . Transaction . Current = clone ;
590
+ if ( ! AutoJoinTransaction )
591
+ s . JoinTransaction ( ) ;
592
+ var count = s . Query < Person > ( ) . Count ( ) ;
593
+ Assert . That ( count , Is . EqualTo ( 1 ) , "Unexpected entity count after committed insert." ) ;
594
+ clone . Complete ( ) ;
595
+ }
596
+
597
+ System . Transactions . Transaction . Current = committable ;
598
+ committable . Commit ( ) ;
599
+ }
600
+ }
601
+ }
602
+ finally
603
+ {
604
+ System . Transactions . Transaction . Current = null ;
605
+ }
606
+
607
+ using ( var s = OpenSession ( ) )
608
+ {
609
+ using ( var tx = new TransactionScope ( ) )
610
+ {
611
+ if ( ! AutoJoinTransaction )
612
+ s . JoinTransaction ( ) ;
613
+ var count = s . Query < Person > ( ) . Count ( ) ;
614
+ Assert . That ( count , Is . EqualTo ( 1 ) , "Unexpected entity count after global commit." ) ;
615
+ tx . Complete ( ) ;
616
+ }
617
+ }
618
+ }
505
619
}
506
620
507
621
[ TestFixture ]
@@ -539,4 +653,4 @@ public void SessionIsNotEnlisted()
539
653
}
540
654
}
541
655
}
542
- }
656
+ }
0 commit comments