diff --git a/doc/reference/modules/configuration.xml b/doc/reference/modules/configuration.xml index a97775563d5..1cfd7e4a180 100644 --- a/doc/reference/modules/configuration.xml +++ b/doc/reference/modules/configuration.xml @@ -905,6 +905,25 @@ var session = sessions.OpenSession(conn); + + + transaction.auto_join + + + Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist + into it if any? + + Default is true. It can also be controlled at session opening, with + ISessionFactory.WithOptions. A session can also be instructed to explicitly join the current + transaction by calling ISession.JoinTransaction. This setting has no effect when using a + transaction factory that is not system transactions aware. + + + eg. + false + + + default_flush_mode diff --git a/doc/reference/modules/transactions.xml b/doc/reference/modules/transactions.xml index 47340ebb931..5a6a7c8dc5a 100644 --- a/doc/reference/modules/transactions.xml +++ b/doc/reference/modules/transactions.xml @@ -633,9 +633,11 @@ finally will then fail to use it. - As of NHibernate v5.0, session auto-enlistment can be disabled from the session builder + Session auto-enlistment can be controlled from the session builder obtained with ISessionFactory.WithOptions(), using the - AutoJoinTransaction option. The connection may still enlist itself + AutoJoinTransaction option. It can also be controlled at the configuration level, + see transaction.auto_join in . + When auto-join is disabled, the connection may still enlist itself if connection string Enlist setting is not false. A session can explicitly join the current system transaction by calling ISession.JoinTransaction(). diff --git a/src/NHibernate.Test/SystemTransactions/AutoJoinSettingFixture.cs b/src/NHibernate.Test/SystemTransactions/AutoJoinSettingFixture.cs new file mode 100644 index 00000000000..6a5af82e42a --- /dev/null +++ b/src/NHibernate.Test/SystemTransactions/AutoJoinSettingFixture.cs @@ -0,0 +1,55 @@ +using System.Transactions; +using NHibernate.Cfg; +using NUnit.Framework; + +namespace NHibernate.Test.SystemTransactions +{ + [TestFixture(true)] + [TestFixture(false)] + [TestFixture(new object[] { null })] + public class AutoJoinSettingFixture : TestCase + { + private readonly bool? _autoJoinTransaction; + + public AutoJoinSettingFixture(bool? autoJoinTransaction) + { + _autoJoinTransaction = autoJoinTransaction; + } + + protected override string[] Mappings => new[] { "TransactionTest.Person.hbm.xml" }; + + protected override string MappingsAssembly => "NHibernate.Test"; + + protected override void Configure(Configuration configuration) + { + if (_autoJoinTransaction.HasValue) + configuration.SetProperty(Environment.AutoJoinTransaction, _autoJoinTransaction.ToString()); + else + configuration.Properties.Remove(Environment.AutoJoinTransaction); + } + + [Test] + public void CheckTransactionJoined() + { + using (new TransactionScope()) + using (var s = OpenSession()) + { + Assert.That( + s.GetSessionImplementation().TransactionContext, + _autoJoinTransaction == false ? Is.Null : Is.Not.Null); + } + } + + [Theory] + public void CanOverrideAutoJoin(bool autoJoin) + { + using (new TransactionScope()) + using (var s = Sfi.WithOptions().AutoJoinTransaction(autoJoin).OpenSession()) + { + Assert.That( + s.GetSessionImplementation().TransactionContext, + autoJoin ? Is.Not.Null : Is.Null); + } + } + } +} diff --git a/src/NHibernate/Cfg/Environment.cs b/src/NHibernate/Cfg/Environment.cs index 5e5dc8238be..0a72d83e0a4 100644 --- a/src/NHibernate/Cfg/Environment.cs +++ b/src/NHibernate/Cfg/Environment.cs @@ -123,6 +123,10 @@ public static string Version [Obsolete("This setting has no usages and will be removed in a future version")] public const string OutputStylesheet = "xml.output_stylesheet"; + /// + /// The class name of a custom implementation. Defaults to the + /// built-in . + /// public const string TransactionStrategy = "transaction.factory_class"; /// /// Timeout duration in milliseconds for the system transaction completion lock. @@ -144,6 +148,14 @@ public static string Version /// transaction preparation, while still benefiting from on querying. /// public const string UseConnectionOnSystemTransactionPrepare = "transaction.use_connection_on_system_prepare"; + /// + /// Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist + /// into it if any? Default is . It can also be controlled at session opening, see + /// . A session can also be instructed to explicitly join the current + /// transaction by calling . This setting has no effect when using a + /// transaction factory that is not system transactions aware. + /// + public const string AutoJoinTransaction = "transaction.auto_join"; // Since v5.0.1 [Obsolete("This setting has no usages and will be removed in a future version")] diff --git a/src/NHibernate/Cfg/Settings.cs b/src/NHibernate/Cfg/Settings.cs index 878b9b60605..4d4fc1fa96e 100644 --- a/src/NHibernate/Cfg/Settings.cs +++ b/src/NHibernate/Cfg/Settings.cs @@ -53,6 +53,15 @@ public Settings() public string SessionFactoryName { get; internal set; } + /// + /// Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist + /// into it if any? Default is . It can also be controlled at session opening, see + /// . A session can also be instructed to explicitly join the current + /// transaction by calling . This setting has no effect if using a + /// transaction factory that is not system transactions aware. + /// + public bool AutoJoinTransaction { get; internal set; } + public bool IsAutoCreateSchema { get; internal set; } public bool IsAutoDropSchema { get; internal set; } @@ -146,4 +155,4 @@ internal string GetFullCacheRegionName(string name) return name; } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Cfg/SettingsFactory.cs b/src/NHibernate/Cfg/SettingsFactory.cs index dd3195350c4..3cb29c0e306 100644 --- a/src/NHibernate/Cfg/SettingsFactory.cs +++ b/src/NHibernate/Cfg/SettingsFactory.cs @@ -291,6 +291,7 @@ public Settings BuildSettings(IDictionary properties) settings.TransactionFactory = transactionFactory; // Not ported - TransactionManagerLookup settings.SessionFactoryName = sessionFactoryName; + settings.AutoJoinTransaction = PropertiesHelper.GetBoolean(Environment.AutoJoinTransaction, properties, true); settings.MaximumFetchDepth = maxFetchDepth; settings.IsQueryCacheEnabled = useQueryCache; settings.IsSecondLevelCacheEnabled = useSecondLevelCache; diff --git a/src/NHibernate/ISession.cs b/src/NHibernate/ISession.cs index bcaf6e5a502..05fe579aafd 100644 --- a/src/NHibernate/ISession.cs +++ b/src/NHibernate/ISession.cs @@ -771,7 +771,8 @@ public partial interface ISession : IDisposable /// /// Sessions auto-join current transaction by default on their first usage within a scope. /// This can be disabled with from - /// a session builder obtained with . + /// a session builder obtained with , or with the + /// auto-join transaction configuration setting. /// /// /// This method allows to explicitly join the current transaction. It does nothing if it is already diff --git a/src/NHibernate/Impl/SessionFactoryImpl.cs b/src/NHibernate/Impl/SessionFactoryImpl.cs index 6547433edc7..ac19e4d962c 100644 --- a/src/NHibernate/Impl/SessionFactoryImpl.cs +++ b/src/NHibernate/Impl/SessionFactoryImpl.cs @@ -1415,7 +1415,7 @@ internal class SessionBuilderImpl : ISessionBuilder, ISessionCreationOptio private ConnectionReleaseMode _connectionReleaseMode; private FlushMode _flushMode; private bool _autoClose; - private bool _autoJoinTransaction = true; + private bool _autoJoinTransaction; public SessionBuilderImpl(SessionFactoryImpl sessionFactory) { @@ -1424,6 +1424,7 @@ public SessionBuilderImpl(SessionFactoryImpl sessionFactory) // set up default builder values... _connectionReleaseMode = sessionFactory.Settings.ConnectionReleaseMode; _autoClose = sessionFactory.Settings.IsAutoCloseSessionEnabled; + _autoJoinTransaction = sessionFactory.Settings.AutoJoinTransaction; // NH different implementation: not using Settings.IsFlushBeforeCompletionEnabled _flushMode = sessionFactory.Settings.DefaultFlushMode; } diff --git a/src/NHibernate/nhibernate-configuration.xsd b/src/NHibernate/nhibernate-configuration.xsd index 7c0a870156f..02519c271b5 100644 --- a/src/NHibernate/nhibernate-configuration.xsd +++ b/src/NHibernate/nhibernate-configuration.xsd @@ -92,7 +92,14 @@ - + + + + The class name of a custom ITransactionFactory implementation. + Defaults to the built-in AdoNetWithSystemTransactionFactory. + + + @@ -174,6 +181,17 @@ + + + + Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist + into it if any? Default is true. It can also be controlled at session opening, with + ISessionFactory.WithOptions. A session can also be instructed to explicitly join the current + transaction by calling ISession.JoinTransaction. This setting has no effect when using a + transaction factory that is not system transactions aware. + + +