Skip to content

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

  1. IsTransactionInProgress() reads the current transaction via Session.Transaction() and returns transaction.IsActive || transaction.WasCommitted || transaction.WasRolledBack. Against NHibernate 5.2.7, Session.Transaction never returns null. After a commit or rollback it returns a new, un-begun transaction, so in practice this check is true only while a transaction is active.
  2. If true: throw InvalidOperationException("There is a transaction already in progress.") (BR-NH-12).
  3. 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).
  4. Call Session.BeginTransaction(IsolationLevel.ReadCommitted) through UnitOfWork.Begin(). This entry point always passes ReadCommitted, and the stateful strategy's BeginTransaction additionally ignores whatever isolation-level argument it is given and always uses ReadCommitted (BR-NH-11). This "no other isolation level" guarantee applies only to the standard UnitOfWork.Begin() entry point: the stateless strategy's BeginTransaction(isolationLevel) honors whatever level is passed to it directly (session.BeginTransaction(isolationLevel)), so a consumer calling ISessionStrategy.BeginTransaction directly on a stateless session — bypassing UnitOfWork.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) throws InvalidOperationException("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 further Begin() 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.

Sources

  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWork.cs
  • src/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