static void TransactionLoop(Action act, Action onChecked) { while (true) { try { _context = new TransactionContextInternal(); _context.Open(); act(); if (_rollback.HasValue) { continue; } if (CommitCheck()) { onChecked(); return; } _context.DoCheckFailed(); } catch (Exception ex) when(IsTransException(ex)) { } finally { if (_context != null) { _context.DoRollback(); } } } }
/// <summary> /// Runs a transaction, with repetitions if needed, until it passes the commit check, /// and then stops. The fields that will be written into, remain locked! It returns /// an object which can be used to later commit the transaction, roll it back, or run /// code inside of its scope, restricted to fields touched by the original transaction. /// Receives a timeout in milliseconds, and the returned continuation will, if not /// completed by then, automatically roll back by this time. /// </summary> public static CommitContinuation RunToCommit(int timeoutMs, Action act) { if (IsInTransaction) { throw new InvalidOperationException("Operation not allowed in transaction."); } CommitContinuation res = null; try { TransactionLoop(act, () => { res = _context; _context = null; }); return(res); } finally { if (res != null && !res.Completed) { res.StartTimer(timeoutMs); } } }