Skip to content

Commit 1c779fa

Browse files
Allow configuring auto-join transaction globally (nhibernate#2214)
1 parent f1aa87f commit 1c779fa

File tree

9 files changed

+124
-6
lines changed

9 files changed

+124
-6
lines changed

doc/reference/modules/configuration.xml

+19
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,25 @@ var session = sessions.OpenSession(conn);
905905
</para>
906906
</entry>
907907
</row>
908+
<row>
909+
<entry>
910+
<literal>transaction.auto_join</literal>
911+
</entry>
912+
<entry>
913+
Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist
914+
into it if any?
915+
<para>
916+
Default is <literal>true</literal>. It can also be controlled at session opening, with
917+
<literal>ISessionFactory.WithOptions</literal>. A session can also be instructed to explicitly join the current
918+
transaction by calling <literal>ISession.JoinTransaction</literal>. This setting has no effect when using a
919+
transaction factory that is not system transactions aware.
920+
</para>
921+
<para>
922+
<emphasis role="strong">eg.</emphasis>
923+
<literal>false</literal>
924+
</para>
925+
</entry>
926+
</row>
908927
<row>
909928
<entry>
910929
<literal>default_flush_mode</literal>

doc/reference/modules/transactions.xml

+4-2
Original file line numberDiff line numberDiff line change
@@ -633,9 +633,11 @@ finally
633633
will then fail to use it.
634634
</para>
635635
<para>
636-
As of NHibernate v5.0, session auto-enlistment can be disabled from the session builder
636+
Session auto-enlistment can be controlled from the session builder
637637
obtained with <literal>ISessionFactory.WithOptions()</literal>, using the
638-
<literal>AutoJoinTransaction</literal> option. The connection may still enlist itself
638+
<literal>AutoJoinTransaction</literal> option. It can also be controlled at the configuration level,
639+
see <literal>transaction.auto_join</literal> in <xref linkend="configuration-optional"/>.
640+
When auto-join is disabled, the connection may still enlist itself
639641
if connection string <literal>Enlist</literal> setting is not <literal>false</literal>.
640642
A session can explicitly join the current system transaction by calling
641643
<literal>ISession.JoinTransaction()</literal>.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System.Transactions;
2+
using NHibernate.Cfg;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.SystemTransactions
6+
{
7+
[TestFixture(true)]
8+
[TestFixture(false)]
9+
[TestFixture(new object[] { null })]
10+
public class AutoJoinSettingFixture : TestCase
11+
{
12+
private readonly bool? _autoJoinTransaction;
13+
14+
public AutoJoinSettingFixture(bool? autoJoinTransaction)
15+
{
16+
_autoJoinTransaction = autoJoinTransaction;
17+
}
18+
19+
protected override string[] Mappings => new[] { "TransactionTest.Person.hbm.xml" };
20+
21+
protected override string MappingsAssembly => "NHibernate.Test";
22+
23+
protected override void Configure(Configuration configuration)
24+
{
25+
if (_autoJoinTransaction.HasValue)
26+
configuration.SetProperty(Environment.AutoJoinTransaction, _autoJoinTransaction.ToString());
27+
else
28+
configuration.Properties.Remove(Environment.AutoJoinTransaction);
29+
}
30+
31+
[Test]
32+
public void CheckTransactionJoined()
33+
{
34+
using (new TransactionScope())
35+
using (var s = OpenSession())
36+
{
37+
Assert.That(
38+
s.GetSessionImplementation().TransactionContext,
39+
_autoJoinTransaction == false ? Is.Null : Is.Not.Null);
40+
}
41+
}
42+
43+
[Theory]
44+
public void CanOverrideAutoJoin(bool autoJoin)
45+
{
46+
using (new TransactionScope())
47+
using (var s = Sfi.WithOptions().AutoJoinTransaction(autoJoin).OpenSession())
48+
{
49+
Assert.That(
50+
s.GetSessionImplementation().TransactionContext,
51+
autoJoin ? Is.Not.Null : Is.Null);
52+
}
53+
}
54+
}
55+
}

src/NHibernate/Cfg/Environment.cs

+12
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ public static string Version
123123
[Obsolete("This setting has no usages and will be removed in a future version")]
124124
public const string OutputStylesheet = "xml.output_stylesheet";
125125

126+
/// <summary>
127+
/// The class name of a custom <see cref="Transaction.ITransactionFactory"/> implementation. Defaults to the
128+
/// built-in <see cref="Transaction.AdoNetWithSystemTransactionFactory" />.
129+
/// </summary>
126130
public const string TransactionStrategy = "transaction.factory_class";
127131
/// <summary>
128132
/// <para>Timeout duration in milliseconds for the system transaction completion lock.</para>
@@ -144,6 +148,14 @@ public static string Version
144148
/// transaction preparation, while still benefiting from <see cref="FlushMode.Auto"/> on querying.
145149
/// </summary>
146150
public const string UseConnectionOnSystemTransactionPrepare = "transaction.use_connection_on_system_prepare";
151+
/// <summary>
152+
/// Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist
153+
/// into it if any? Default is <see langword="true"/>. It can also be controlled at session opening, see
154+
/// <see cref="ISessionFactory.WithOptions" />. A session can also be instructed to explicitly join the current
155+
/// transaction by calling <see cref="ISession.JoinTransaction" />. This setting has no effect when using a
156+
/// transaction factory that is not system transactions aware.
157+
/// </summary>
158+
public const string AutoJoinTransaction = "transaction.auto_join";
147159

148160
// Since v5.0.1
149161
[Obsolete("This setting has no usages and will be removed in a future version")]

src/NHibernate/Cfg/Settings.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ public Settings()
5353

5454
public string SessionFactoryName { get; internal set; }
5555

56+
/// <summary>
57+
/// Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist
58+
/// into it if any? Default is <see langword="true"/>. It can also be controlled at session opening, see
59+
/// <see cref="ISessionFactory.WithOptions" />. A session can also be instructed to explicitly join the current
60+
/// transaction by calling <see cref="ISession.JoinTransaction" />. This setting has no effect if using a
61+
/// transaction factory that is not system transactions aware.
62+
/// </summary>
63+
public bool AutoJoinTransaction { get; internal set; }
64+
5665
public bool IsAutoCreateSchema { get; internal set; }
5766

5867
public bool IsAutoDropSchema { get; internal set; }
@@ -146,4 +155,4 @@ internal string GetFullCacheRegionName(string name)
146155
return name;
147156
}
148157
}
149-
}
158+
}

src/NHibernate/Cfg/SettingsFactory.cs

+1
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ public Settings BuildSettings(IDictionary<string, string> properties)
291291
settings.TransactionFactory = transactionFactory;
292292
// Not ported - TransactionManagerLookup
293293
settings.SessionFactoryName = sessionFactoryName;
294+
settings.AutoJoinTransaction = PropertiesHelper.GetBoolean(Environment.AutoJoinTransaction, properties, true);
294295
settings.MaximumFetchDepth = maxFetchDepth;
295296
settings.IsQueryCacheEnabled = useQueryCache;
296297
settings.IsSecondLevelCacheEnabled = useSecondLevelCache;

src/NHibernate/ISession.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,8 @@ public partial interface ISession : IDisposable
771771
/// <para>
772772
/// Sessions auto-join current transaction by default on their first usage within a scope.
773773
/// This can be disabled with <see cref="ISessionBuilder{T}.AutoJoinTransaction(bool)"/> from
774-
/// a session builder obtained with <see cref="ISessionFactory.WithOptions()"/>.
774+
/// a session builder obtained with <see cref="ISessionFactory.WithOptions()"/>, or with the
775+
/// auto-join transaction configuration setting.
775776
/// </para>
776777
/// <para>
777778
/// This method allows to explicitly join the current transaction. It does nothing if it is already

src/NHibernate/Impl/SessionFactoryImpl.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1415,7 +1415,7 @@ internal class SessionBuilderImpl<T> : ISessionBuilder<T>, ISessionCreationOptio
14151415
private ConnectionReleaseMode _connectionReleaseMode;
14161416
private FlushMode _flushMode;
14171417
private bool _autoClose;
1418-
private bool _autoJoinTransaction = true;
1418+
private bool _autoJoinTransaction;
14191419

14201420
public SessionBuilderImpl(SessionFactoryImpl sessionFactory)
14211421
{
@@ -1424,6 +1424,7 @@ public SessionBuilderImpl(SessionFactoryImpl sessionFactory)
14241424
// set up default builder values...
14251425
_connectionReleaseMode = sessionFactory.Settings.ConnectionReleaseMode;
14261426
_autoClose = sessionFactory.Settings.IsAutoCloseSessionEnabled;
1427+
_autoJoinTransaction = sessionFactory.Settings.AutoJoinTransaction;
14271428
// NH different implementation: not using Settings.IsFlushBeforeCompletionEnabled
14281429
_flushMode = sessionFactory.Settings.DefaultFlushMode;
14291430
}

src/NHibernate/nhibernate-configuration.xsd

+19-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,14 @@
9292
<xs:enumeration value="show_sql" />
9393
<xs:enumeration value="max_fetch_depth" />
9494
<xs:enumeration value="current_session_context_class" />
95-
<xs:enumeration value="transaction.factory_class" />
95+
<xs:enumeration value="transaction.factory_class">
96+
<xs:annotation>
97+
<xs:documentation>
98+
The class name of a custom ITransactionFactory implementation.
99+
Defaults to the built-in AdoNetWithSystemTransactionFactory.
100+
</xs:documentation>
101+
</xs:annotation>
102+
</xs:enumeration>
96103
<xs:enumeration value="cache.provider_class" />
97104
<xs:enumeration value="cache.use_query_cache" />
98105
<xs:enumeration value="cache.query_cache_factory" />
@@ -174,6 +181,17 @@
174181
</xs:documentation>
175182
</xs:annotation>
176183
</xs:enumeration>
184+
<xs:enumeration value="transaction.auto_join">
185+
<xs:annotation>
186+
<xs:documentation>
187+
Should sessions check on every operation whether there is an ongoing system transaction or not, and enlist
188+
into it if any? Default is true. It can also be controlled at session opening, with
189+
ISessionFactory.WithOptions. A session can also be instructed to explicitly join the current
190+
transaction by calling ISession.JoinTransaction. This setting has no effect when using a
191+
transaction factory that is not system transactions aware.
192+
</xs:documentation>
193+
</xs:annotation>
194+
</xs:enumeration>
177195
<xs:enumeration value="oracle.use_n_prefixed_types_for_unicode">
178196
<xs:annotation>
179197
<xs:documentation>

0 commit comments

Comments
 (0)