@@ -49,6 +49,8 @@ protected override void CreateSchema()
49
49
50
50
protected override void OnTearDown ( )
51
51
{
52
+ DodgeTransactionCompletionDelayIfRequired ( ) ;
53
+
52
54
using ( var s = OpenSession ( ) )
53
55
using ( var t = s . BeginTransaction ( ) )
54
56
{
@@ -505,11 +507,53 @@ public void CanUseSessionOutsideOfScopeAfterScope([Values(false, true)] bool exp
505
507
Assert . DoesNotThrow ( ( ) => count = s . Query < Person > ( ) . Count ( ) , "Failed using the session after scope." ) ;
506
508
if ( count != 1 )
507
509
// We are not testing that here, so just issue a warning. Do not use DodgeTransactionCompletionDelayIfRequired
508
- // before previous assert. We want to ascertain the session is usable in any cases.
510
+ // before previous assert. We want to ascertain the session is usable in any cases.
509
511
Assert . Warn ( "Unexpected entity count: {0} instead of {1}. The transaction seems to have a delayed commit." , count , 1 ) ;
510
512
}
511
513
}
512
514
515
+ [ Test ( Description = "Do not fail, but warn in case a delayed after scope disposal commit is made." ) ]
516
+ public void DelayedTransactionCompletion ( [ Values ( false , true ) ] bool explicitFlush )
517
+ {
518
+ for ( var i = 1 ; i <= 10 ; i ++ )
519
+ {
520
+ // Isolation level must be read committed on the control session: reading twice while expecting some data insert
521
+ // in between due to a late commit. Repeatable read would block and read uncommitted would see the uncommitted data.
522
+ using ( var controlSession = OpenSession ( ) )
523
+ using ( controlSession . BeginTransaction ( System . Data . IsolationLevel . ReadCommitted ) )
524
+ {
525
+ // We want to have the control session as ready to query as possible, thus beginning its
526
+ // transaction early for acquiring the connection, even if we will not use it before
527
+ // below scope completion.
528
+
529
+ using ( var tx = new TransactionScope ( ) )
530
+ {
531
+ using ( var s = OpenSession ( ) )
532
+ {
533
+ s . Save ( new Person { CreatedAt = DateTime . Today } ) ;
534
+
535
+ ForceEscalationToDistributedTx . Escalate ( ) ;
536
+
537
+ if ( explicitFlush )
538
+ s . Flush ( ) ;
539
+ }
540
+ tx . Complete ( ) ;
541
+ }
542
+
543
+ var count = controlSession . Query < Person > ( ) . Count ( ) ;
544
+ if ( count != i )
545
+ {
546
+ Thread . Sleep ( 100 ) ;
547
+ var countSecondTry = controlSession . Query < Person > ( ) . Count ( ) ;
548
+ Assert . Warn ( $ "Unexpected entity count: { count } instead of { i } . " +
549
+ "This may mean current data provider has a delayed commit, occurring after scope disposal. " +
550
+ $ "After waiting, count is now { countSecondTry } . ") ;
551
+ break ;
552
+ }
553
+ }
554
+ }
555
+ }
556
+
513
557
private void AssertNoPersons ( )
514
558
{
515
559
using ( var s = OpenSession ( ) )
0 commit comments