Begin transaction¶
This operation starts a new transaction on the unit of work's session. It refuses only while another transaction on that session is still active. On a stateful session it first clears the session so in-memory state starts in sync with the database; on a stateless session, clearing is a no-op (there is no first-level cache to discard).
| Field | Value |
|---|---|
| Operation ID | OP-NH-07 |
| Trigger | Consumer calls IUnitOfWork.Begin() |
| Inputs | — |
| Outputs | An active ReadCommitted transaction on the unit of work's session, or a thrown exception |
| Primary components | UnitOfWork.Begin, IsTransactionInProgress |
| Entry point | src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWork.cs |
Steps¶
IsTransactionInProgress()reads the current transaction viaSession.Transaction()and returnstransaction.IsActive || transaction.WasCommitted || transaction.WasRolledBack. Against NHibernate 5.2.7,Session.Transactionnever returnsnull. After a commit or rollback it returns a new, un-begun transaction, so in practice this check istrueonly while a transaction is active.- If
true: throwInvalidOperationException("There is a transaction already in progress.")(BR-NH-12). - If no transaction is in progress: call
Session.Clear(). On the stateful strategy this discards any uncommitted changes held in NHibernate's first-level cache, keeping the session and database in sync. On the stateless strategy,Clear()is a literal no-op ({ }— there is no first-level cache for a stateless session to discard). - Call
Session.BeginTransaction(IsolationLevel.ReadCommitted)throughUnitOfWork.Begin(). This entry point always passesReadCommitted, and the stateful strategy'sBeginTransactionadditionally ignores whatever isolation-level argument it is given and always usesReadCommitted(BR-NH-11). This "no other isolation level" guarantee applies only to the standardUnitOfWork.Begin()entry point: the stateless strategy'sBeginTransaction(isolationLevel)honors whatever level is passed to it directly (session.BeginTransaction(isolationLevel)), so a consumer callingISessionStrategy.BeginTransactiondirectly on a stateless session — bypassingUnitOfWork.Begin()— can select a different isolation level.
Begin itself issues no SQL, but it is the first step of Test connection's Begin/query/Commit cycle, which does execute SQL-004.
Process flow¶
The diagram below visualizes the transaction-in-progress guard and the clear/begin-transaction path taken when no transaction is already active.
flowchart TD
Start(["Begin() called"]) --> Check{"Current transaction<br>still active?"}
Check -->|Yes| Throw(["Throw InvalidOperationException"])
Check -->|No| Clear["Session.Clear()<br>(stateful: discards cache; stateless: no-op)"]
Clear --> BeginTx["Session.BeginTransaction(ReadCommitted)"]
BeginTx --> Return(["Transaction active"])
Failure and edge-case behavior¶
- Calling
Begin()again while the previous transaction is still active (not yet committed or rolled back) throwsInvalidOperationException("There is a transaction already in progress."). - After a successful Commit, the session stays open. Against NHibernate 5.2.7, NHibernate detaches the committed transaction from the session (
ConnectionManager.AfterTransaction()sets_transaction = null), so a furtherBegin()on the same unit of work starts a new transaction and does not throw. - After Rollback, the unit of work disposes its session. Whether a later
Begin()on that unit of work succeeds depends on the session strategy and is not confirmed by this library's source. - Recommended practice: use a new unit of work for each transaction and dispose it when the work is done. This is a convention, not a restriction the library enforces.
Related documentation¶
Sources¶
src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWork.cssrc/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionStrategies/StatefulSessionStrategy.cs- NHibernate 5.2.7 (resolved via FluentNHibernate 3.0.1):
src/NHibernate/AdoNet/ConnectionManager.cs(Transaction,AfterTransaction),src/NHibernate/Transaction/AdoTransaction.cs(Commit,AfterTransactionCompletion,IsActive),src/NHibernate/Transaction/AdoNetTransactionFactory.cs(CreateTransaction) src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionStrategies/StatelessSessionStrategy.cs