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