6
6
7
7
using System ;
8
8
using System . Collections . Generic ;
9
+ using System . Data . Common ;
9
10
using System . Threading ;
10
11
using System . Threading . Tasks ;
11
12
using System . Transactions ;
@@ -28,12 +29,7 @@ public sealed partial class Transaction : IHasExtensions
28
29
/// Gets the current <see cref="Transaction"/> object
29
30
/// using <see cref="Session"/>.<see cref="Orm.Session.Current"/>.
30
31
/// </summary>
31
- public static Transaction Current {
32
- get {
33
- var session = Session . Current ;
34
- return session ? . Transaction ;
35
- }
36
- }
32
+ public static Transaction Current => Session . Current ? . Transaction ;
37
33
38
34
/// <summary>
39
35
/// Gets the current <see cref="Transaction"/>,
@@ -44,16 +40,8 @@ public static Transaction Current {
44
40
/// <exception cref="InvalidOperationException">
45
41
/// <see cref="Transaction.Current"/> <see cref="Transaction"/> is <see langword="null" />.
46
42
/// </exception>
47
- public static Transaction Demand ( )
48
- {
49
- var current = Current ;
50
- if ( current == null ) {
51
- throw new InvalidOperationException (
52
- Strings . ExActiveTransactionIsRequiredForThisOperationUseSessionOpenTransactionToOpenIt ) ;
53
- }
54
-
55
- return current ;
56
- }
43
+ public static Transaction Demand ( ) =>
44
+ Current ?? throw new InvalidOperationException ( Strings . ExActiveTransactionIsRequiredForThisOperationUseSessionOpenTransactionToOpenIt ) ;
57
45
58
46
/// <summary>
59
47
/// Checks whether a transaction exists or not in the provided session.
@@ -68,58 +56,70 @@ public static void Require(Session session)
68
56
69
57
#endregion
70
58
71
- private readonly List < StateLifetimeToken > lifetimeTokens ;
59
+ private readonly List < StateLifetimeToken > lifetimeTokens = new ( 1 ) ;
72
60
73
61
private ExtensionCollection extensions ;
74
62
private Transaction inner ;
75
63
76
64
/// <summary>
77
65
/// Gets a value indicating whether this instance is automatic transaction.
78
66
/// </summary>
79
- public bool IsAutomatic { get ; private set ; }
80
-
67
+ public bool IsAutomatic { get ; }
68
+
81
69
/// <summary>
82
70
/// Gets a value indicating whether this instance is
83
71
/// transaction running locally.
84
72
/// </summary>
85
- public bool IsDisconnected { get ; private set ; }
86
-
73
+ public bool IsDisconnected { get ; }
74
+
75
+ private Guid ? guid ;
87
76
/// <summary>
88
77
/// Gets the unique identifier of this transaction.
89
78
/// Nested transactions have the same <see cref="Guid"/>
90
79
/// as their outermost.
91
80
/// </summary>
92
- public Guid Guid { get ; private set ; }
81
+ public Guid Guid => Outer ? . Guid ?? ( guid ??= Guid . NewGuid ( ) ) ;
93
82
94
83
/// <summary>
95
84
/// Gets the session this transaction is bound to.
96
85
/// </summary>
97
- public Session Session { get ; private set ; }
86
+ public Session Session { get ; }
98
87
99
88
/// <summary>
100
89
/// Gets the isolation level.
101
90
/// </summary>
102
- public IsolationLevel IsolationLevel { get ; private set ; }
91
+ public IsolationLevel IsolationLevel { get ; }
103
92
104
93
/// <summary>
105
94
/// Gets the state of the transaction.
106
95
/// </summary>
107
- public TransactionState State { get ; private set ; }
96
+ public TransactionState State { get ; private set ; } = TransactionState . NotActivated ;
108
97
109
98
/// <summary>
110
99
/// Gets the outer transaction.
111
100
/// </summary>
112
- public Transaction Outer { get ; private set ; }
101
+ public Transaction Outer { get ; }
113
102
114
103
/// <summary>
115
104
/// Gets the outermost transaction.
116
105
/// </summary>
117
- public Transaction Outermost { get ; private set ; }
106
+ public Transaction Outermost => Outer ? . Outermost ?? this ;
118
107
119
108
/// <summary>
120
109
/// Gets the start time of this transaction.
121
110
/// </summary>
122
- public DateTime TimeStamp { get ; private set ; }
111
+ public DateTime TimeStamp { get ; } = DateTime . UtcNow ;
112
+
113
+ private TimeSpan ? timeout ;
114
+ /// <summary>
115
+ /// Gets or sets Transaction timeout
116
+ /// </summary>
117
+ public TimeSpan ? Timeout {
118
+ get => timeout ;
119
+ set => timeout = IsNested
120
+ ? throw new InvalidOperationException ( Strings . ExNestedTransactionTimeout )
121
+ : value ;
122
+ }
123
123
124
124
/// <summary>
125
125
/// Gets a value indicating whether this transaction is a nested transaction.
@@ -129,7 +129,7 @@ public static void Require(Session session)
129
129
/// <summary>
130
130
/// Gets <see cref="StateLifetimeToken"/> associated with this transaction.
131
131
/// </summary>
132
- public StateLifetimeToken LifetimeToken { get ; private set ; }
132
+ public StateLifetimeToken LifetimeToken { get ; private set ; } = new ( ) ;
133
133
134
134
#region IHasExtensions Members
135
135
@@ -138,7 +138,7 @@ public static void Require(Session session)
138
138
139
139
#endregion
140
140
141
- internal string SavepointName { get ; private set ; }
141
+ internal string SavepointName { get ; }
142
142
143
143
/// <summary>
144
144
/// Indicates whether changes made in this transaction are visible "as is"
@@ -278,40 +278,34 @@ private void ClearLifetimeTokens()
278
278
LifetimeToken = null ;
279
279
}
280
280
281
+ internal void CheckForTimeout ( DbCommand command )
282
+ {
283
+ if ( Timeout is not null ) {
284
+ var remain = TimeStamp + Timeout . Value - DateTime . UtcNow ;
285
+ command . CommandTimeout = remain . Ticks > 0
286
+ ? Math . Max ( 1 , ( int ) remain . TotalSeconds )
287
+ : throw new TimeoutException ( String . Format ( Strings . ExTransactionTimeout , Timeout ) ) ;
288
+ }
289
+ }
290
+
281
291
#endregion
282
292
283
-
284
- // Constructors
285
293
286
- internal Transaction ( Session session , IsolationLevel isolationLevel , bool isAutomatic )
287
- : this ( session , isolationLevel , isAutomatic , null , null )
288
- {
289
- }
294
+ // Constructors
290
295
291
- internal Transaction ( Session session , IsolationLevel isolationLevel , bool isAutomatic , Transaction outer ,
292
- string savepointName )
296
+ internal Transaction ( Session session , IsolationLevel isolationLevel , bool isAutomatic , Transaction outer = null ,
297
+ string savepointName = null )
293
298
{
294
- lifetimeTokens = new List < StateLifetimeToken > ( ) ;
295
-
296
- Guid = Guid . NewGuid ( ) ;
297
- State = TransactionState . NotActivated ;
298
299
Session = session ;
299
300
IsolationLevel = isolationLevel ;
300
301
IsAutomatic = isAutomatic ;
301
302
IsDisconnected = session . IsDisconnected ;
302
- TimeStamp = DateTime . UtcNow ;
303
- LifetimeToken = new StateLifetimeToken ( ) ;
304
303
lifetimeTokens . Add ( LifetimeToken ) ;
305
304
306
305
if ( outer != null ) {
307
306
Outer = outer ;
308
- Guid = outer . Guid ;
309
- Outermost = outer . Outermost ;
310
307
SavepointName = savepointName ;
311
308
}
312
- else {
313
- Outermost = this ;
314
- }
315
309
}
316
310
}
317
- }
311
+ }
0 commit comments