/src/NHibernate.Test/SystemTransactions/SystemTransactionFixtureBase.cs

https://github.com/RogerKratz/nhibernate-core · C# · 154 lines · 123 code · 17 blank · 14 comment · 6 complexity · 0af2ea0d96b142bd5e51a29b5c18bb88 MD5 · raw file

  1. using System;
  2. using System.Text.RegularExpressions;
  3. using NHibernate.Cfg;
  4. using NHibernate.Driver;
  5. using NHibernate.Engine;
  6. using NHibernate.Test.TransactionTest;
  7. using NHibernate.Util;
  8. using NUnit.Framework;
  9. namespace NHibernate.Test.SystemTransactions
  10. {
  11. public abstract class SystemTransactionFixtureBase : TransactionFixtureBase
  12. {
  13. protected override bool AppliesTo(ISessionFactoryImplementor factory)
  14. => factory.ConnectionProvider.Driver.SupportsSystemTransactions && base.AppliesTo(factory);
  15. protected abstract bool UseConnectionOnSystemTransactionPrepare { get; }
  16. protected abstract bool AutoJoinTransaction { get; }
  17. protected override void Configure(Configuration configuration)
  18. {
  19. base.Configure(configuration);
  20. configuration
  21. .SetProperty(
  22. Cfg.Environment.UseConnectionOnSystemTransactionPrepare,
  23. UseConnectionOnSystemTransactionPrepare.ToString());
  24. }
  25. protected void DisableConnectionAutoEnlist(Configuration configuration)
  26. {
  27. var connectionString = configuration.GetProperty(Cfg.Environment.ConnectionString);
  28. var autoEnlistmentKeyword = "Enlist";
  29. var autoEnlistmentKeywordPattern = autoEnlistmentKeyword;
  30. if (configuration.GetDerivedProperties().TryGetValue(Cfg.Environment.ConnectionDriver, out var driver) &&
  31. typeof(MySqlDataDriver).IsAssignableFrom(ReflectHelper.ClassForName(driver)))
  32. {
  33. autoEnlistmentKeyword = "AutoEnlist";
  34. autoEnlistmentKeywordPattern = "Auto ?Enlist";
  35. }
  36. // Purge any previous enlist
  37. connectionString = Regex.Replace(
  38. connectionString, $"[^;\"a-zA-Z]*{autoEnlistmentKeywordPattern}=[^;\"]*;?", string.Empty,
  39. RegexOptions.IgnoreCase);
  40. // Avoid redundant semi-colon
  41. connectionString = Regex.Replace(
  42. connectionString, $";[/s]*$", string.Empty,
  43. RegexOptions.IgnoreCase);
  44. connectionString += $";{autoEnlistmentKeyword}=false;";
  45. configuration.SetProperty(Cfg.Environment.ConnectionString, connectionString);
  46. }
  47. protected void IgnoreIfUnsupported(bool explicitFlush)
  48. {
  49. Assume.That(
  50. new[]
  51. {
  52. explicitFlush,
  53. UseConnectionOnSystemTransactionPrepare && TestDialect.SupportsUsingConnectionOnSystemTransactionPrepare
  54. },
  55. Has.Some.EqualTo(true),
  56. "Implicit flush cannot work without using connection from system transaction prepare phase");
  57. }
  58. /// <summary>
  59. /// Open a session, manually enlisting it into ambient transaction if there is one.
  60. /// </summary>
  61. /// <returns>An newly opened session.</returns>
  62. protected override ISession OpenSession()
  63. {
  64. if (AutoJoinTransaction)
  65. return base.OpenSession();
  66. var session = Sfi.WithOptions().AutoJoinTransaction(false).OpenSession();
  67. if (System.Transactions.Transaction.Current != null)
  68. session.JoinTransaction();
  69. return session;
  70. }
  71. /// <summary>
  72. /// <c>WithOptions</c> having already set up <c>AutoJoinTransaction()</c>
  73. /// according to the fixture <see cref="AutoJoinTransaction"/> property.
  74. /// </summary>
  75. /// <returns>A session builder.</returns>
  76. protected ISessionBuilder WithOptions()
  77. {
  78. return Sfi.WithOptions().AutoJoinTransaction(AutoJoinTransaction);
  79. }
  80. public class AfterTransactionWaitingInterceptor : EmptyInterceptor
  81. {
  82. private ISession _session;
  83. public Exception Exception { get; private set; }
  84. public override void SetSession(ISession session)
  85. {
  86. _session = session;
  87. }
  88. public override void AfterTransactionCompletion(ITransaction tx)
  89. {
  90. try
  91. {
  92. // Simulate an action causing a Wait
  93. _session.GetSessionImplementation().TransactionContext?.Wait();
  94. }
  95. catch (Exception ex)
  96. {
  97. Exception = ex;
  98. throw;
  99. }
  100. }
  101. }
  102. public class TransactionCompleteUsingConnectionInterceptor : EmptyInterceptor
  103. {
  104. private ISession _session;
  105. public Exception BeforeException { get; private set; }
  106. public Exception AfterException { get; private set; }
  107. public override void SetSession(ISession session)
  108. {
  109. _session = session;
  110. }
  111. public override void BeforeTransactionCompletion(ITransaction tx)
  112. {
  113. try
  114. {
  115. // Simulate an action causing a connection usage.
  116. _session.Connection.ToString();
  117. }
  118. catch (Exception ex)
  119. {
  120. BeforeException = ex;
  121. }
  122. }
  123. public override void AfterTransactionCompletion(ITransaction tx)
  124. {
  125. try
  126. {
  127. // Simulate an action causing a connection usage.
  128. _session.Connection.ToString();
  129. }
  130. catch (Exception ex)
  131. {
  132. AfterException = ex;
  133. }
  134. }
  135. }
  136. }
  137. }