1
1
using System ;
2
2
using System . Collections ;
3
+ using System . Threading ;
3
4
using System . Transactions ;
4
5
using NHibernate . Engine ;
5
6
using NHibernate . Engine . Transaction ;
@@ -29,54 +30,14 @@ public void EnlistInDistributedTransactionIfNeeded(ISessionImplementor session)
29
30
30
31
if ( System . Transactions . Transaction . Current == null )
31
32
return ;
32
-
33
- var transactionContext = new DistributedTransactionContext ( session ,
34
- System . Transactions . Transaction . Current ) ;
35
- session . TransactionContext = transactionContext ;
36
- logger . DebugFormat ( "enlisted into DTC transaction: {0}" ,
37
- transactionContext . AmbientTransation . IsolationLevel ) ;
38
- session . AfterTransactionBegin ( null ) ;
39
-
40
- TransactionCompletedEventHandler handler = null ;
41
-
42
- handler = delegate ( object sender , TransactionEventArgs e )
43
- {
44
- using ( new SessionIdLoggingContext ( session . SessionId ) )
45
- {
46
- ( ( DistributedTransactionContext ) session . TransactionContext ) . IsInActiveTransaction = false ;
47
-
48
- bool wasSuccessful = false ;
49
- try
50
- {
51
- wasSuccessful = e . Transaction . TransactionInformation . Status
52
- == TransactionStatus . Committed ;
53
- }
54
- catch ( ObjectDisposedException ode )
55
- {
56
- logger . Warn ( "Completed transaction was disposed, assuming transaction rollback" , ode ) ;
57
- }
58
- session . AfterTransactionCompletion ( wasSuccessful , null ) ;
59
- if ( transactionContext . ShouldCloseSessionOnDistributedTransactionCompleted )
60
- {
61
- session . CloseSessionFromDistributedTransaction ( ) ;
62
- }
63
- session . TransactionContext = null ;
64
- }
65
-
66
- e . Transaction . TransactionCompleted -= handler ;
67
- } ;
68
33
69
- transactionContext . AmbientTransation . TransactionCompleted += handler ;
70
-
71
- transactionContext . AmbientTransation . EnlistVolatile ( transactionContext ,
72
- EnlistmentOptions . EnlistDuringPrepareRequired ) ;
34
+ new DistributedTransactionContext ( session , System . Transactions . Transaction . Current ) ;
73
35
}
74
36
75
37
public bool IsInDistributedActiveTransaction ( ISessionImplementor session )
76
38
{
77
- var distributedTransactionContext = ( ( DistributedTransactionContext ) session . TransactionContext ) ;
78
- return distributedTransactionContext != null &&
79
- distributedTransactionContext . IsInActiveTransaction ;
39
+ var distributedTransactionContext = ( DistributedTransactionContext ) session . TransactionContext ;
40
+ return distributedTransactionContext != null ;
80
41
}
81
42
82
43
public void ExecuteWorkInIsolation ( ISessionImplementor session , IIsolatedWork work , bool transacted )
@@ -92,35 +53,37 @@ public void ExecuteWorkInIsolation(ISessionImplementor session, IIsolatedWork wo
92
53
93
54
public class DistributedTransactionContext : ITransactionContext , IEnlistmentNotification
94
55
{
95
- public System . Transactions . Transaction AmbientTransation { get ; set ; }
96
- public bool ShouldCloseSessionOnDistributedTransactionCompleted { get ; set ; }
97
- private ISessionImplementor sessionImplementor ;
98
- public bool IsInActiveTransaction ;
56
+ public bool ShouldCloseSessionOnDistributedTransactionCompleted { get ; set ; }
57
+
58
+ System . Transactions . Transaction _transaction ;
59
+ ISessionImplementor _session ;
99
60
100
- public DistributedTransactionContext ( ISessionImplementor sessionImplementor , System . Transactions . Transaction transaction )
61
+ public DistributedTransactionContext ( ISessionImplementor session , System . Transactions . Transaction transaction )
101
62
{
102
- this . sessionImplementor = sessionImplementor ;
103
- AmbientTransation = transaction . Clone ( ) ;
104
- IsInActiveTransaction = true ;
63
+ _session = session ;
64
+ _session . TransactionContext = this ;
65
+ _transaction = transaction . Clone ( ) ;
66
+ logger . DebugFormat ( "enlisted into DTC transaction: {0}" ,
67
+ _transaction . IsolationLevel ) ;
68
+ _session . AfterTransactionBegin ( null ) ;
69
+ _transaction . EnlistVolatile ( this , EnlistmentOptions . EnlistDuringPrepareRequired ) ;
105
70
}
106
71
107
- #region IEnlistmentNotification Members
108
-
109
72
void IEnlistmentNotification . Prepare ( PreparingEnlistment preparingEnlistment )
110
73
{
111
- using ( new SessionIdLoggingContext ( sessionImplementor . SessionId ) )
74
+ using ( new SessionIdLoggingContext ( _session . SessionId ) )
112
75
{
113
76
try
114
77
{
115
- using ( var tx = new TransactionScope ( AmbientTransation ) )
78
+ using ( var tx = new TransactionScope ( _transaction ) )
116
79
{
117
- sessionImplementor . BeforeTransactionCompletion ( null ) ;
118
- if ( sessionImplementor . FlushMode != FlushMode . Never && sessionImplementor . ConnectionManager . IsConnected )
80
+ _session . BeforeTransactionCompletion ( null ) ;
81
+ if ( _session . FlushMode != FlushMode . Never && _session . ConnectionManager . IsConnected )
119
82
{
120
- using ( sessionImplementor . ConnectionManager . FlushingFromDtcTransaction )
83
+ using ( _session . ConnectionManager . FlushingFromDtcTransaction )
121
84
{
122
- logger . Debug ( string . Format ( "[session-id={0}] Flushing from Dtc Transaction" , sessionImplementor . SessionId ) ) ;
123
- sessionImplementor . Flush ( ) ;
85
+ logger . Debug ( String . Format ( "[session-id={0}] Flushing from Dtc Transaction" , _session . SessionId ) ) ;
86
+ _session . Flush ( ) ;
124
87
}
125
88
}
126
89
logger . Debug ( "prepared for DTC transaction" ) ;
@@ -132,55 +95,65 @@ void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment)
132
95
catch ( Exception exception )
133
96
{
134
97
logger . Error ( "DTC transaction prepare phase failed" , exception ) ;
98
+ OnTransactionCompletion ( false ) ;
135
99
preparingEnlistment . ForceRollback ( exception ) ;
136
100
}
137
101
}
138
102
}
139
103
140
104
void IEnlistmentNotification . Commit ( Enlistment enlistment )
141
105
{
142
- using ( new SessionIdLoggingContext ( sessionImplementor . SessionId ) )
106
+ using ( new SessionIdLoggingContext ( _session . SessionId ) )
143
107
{
144
108
logger . Debug ( "committing DTC transaction" ) ;
145
- // we have nothing to do here, since it is the actual
146
- // DB connection that will commit the transaction
147
- enlistment . Done ( ) ;
148
- IsInActiveTransaction = false ;
109
+ OnTransactionCompletion ( true ) ;
149
110
}
111
+ enlistment . Done ( ) ;
150
112
}
151
113
152
114
void IEnlistmentNotification . Rollback ( Enlistment enlistment )
153
115
{
154
- using ( new SessionIdLoggingContext ( sessionImplementor . SessionId ) )
116
+ using ( new SessionIdLoggingContext ( _session . SessionId ) )
155
117
{
156
118
logger . Debug ( "rolled back DTC transaction" ) ;
157
- // Currently AfterTransactionCompletion is called by the handler for the TransactionCompleted event.
158
- //sessionImplementor.AfterTransactionCompletion(false, null);
159
- enlistment . Done ( ) ;
160
- IsInActiveTransaction = false ;
119
+ OnTransactionCompletion ( false ) ;
161
120
}
121
+ enlistment . Done ( ) ;
162
122
}
163
123
164
124
void IEnlistmentNotification . InDoubt ( Enlistment enlistment )
165
125
{
166
- using ( new SessionIdLoggingContext ( sessionImplementor . SessionId ) )
126
+ using ( new SessionIdLoggingContext ( _session . SessionId ) )
167
127
{
168
- sessionImplementor . AfterTransactionCompletion ( false , null ) ;
169
128
logger . Debug ( "DTC transaction is in doubt" ) ;
170
- enlistment . Done ( ) ;
171
- IsInActiveTransaction = false ;
129
+ OnTransactionCompletion ( false ) ;
172
130
}
131
+ enlistment . Done ( ) ;
173
132
}
174
133
175
- #endregion
176
-
177
134
public void Dispose ( )
178
135
{
179
- if ( AmbientTransation != null )
180
- AmbientTransation . Dispose ( ) ;
181
- AmbientTransation = null ;
182
- sessionImplementor = null ;
183
- }
136
+ if ( _transaction != null )
137
+ _transaction . Dispose ( ) ;
138
+ _transaction = null ;
139
+ if ( _session != null )
140
+ _session . TransactionContext = null ;
141
+ _session = null ;
142
+ }
143
+
144
+ void OnTransactionCompletion ( bool wasSuccessful )
145
+ {
146
+ using ( new SessionIdLoggingContext ( _session . SessionId ) )
147
+ {
148
+ _session . TransactionContext = null ;
149
+ _session . AfterTransactionCompletion ( wasSuccessful , null ) ;
150
+ if ( ShouldCloseSessionOnDistributedTransactionCompleted )
151
+ {
152
+ _session . CloseSessionFromDistributedTransaction ( ) ;
153
+ }
154
+ Dispose ( ) ;
155
+ }
156
+ }
184
157
}
185
158
}
186
159
}
0 commit comments