---
title: SAIF.NetCore.NHibernate operations and processes
summary: Business and technical operations supported by this library.
status: draft
owner: Framework
last_reviewed: 2026-10-02
library: SAIF.NetCore.NHibernate
reference_type: package
---

# SAIF.NetCore.NHibernate operations and processes

This page is the operation catalog and cross-operation hub for this library. Each operation's detailed, step-by-step logic lives in its own page under `operations/`.

## Operation catalog

| Operation | Intent | Trigger | Inputs | Outputs | Rules | Tables | SQL |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [Register NHibernate services](operations/register-nhibernate-services.md) | Register the singleton unit-of-work factory and scoped accessor with DI | Host calls `AddNhibernateServices`/`AddNhibernateServices<T>` at startup | Mapping assemblies, `debugOutputSql` | `IUnitOfWorkFactory` singleton, `UnitOfWorkAccessor` scoped service | [BR-NH-01](business-rules.md#br-nh-01-mapping-assemblies-fixed-at-registration) | — | — |
| [Configure named unit-of-work options](operations/configure-named-unit-of-work-options.md) | Resolve and cache a connection string and engine for one named database | `IOptionsSnapshot<UnitOfWorkOptions>.Get(name)` runs registered configurers | `IEnvironmentClient`, `IDBConnectionClient` | Populated `UnitOfWorkOptions.Name`/`Database`/`ConnectionString` | [BR-NH-02](business-rules.md#br-nh-02-options-applied-only-to-matching-named-instance), [BR-NH-03](business-rules.md#br-nh-03-connection-string-resolved-once-at-construction) | — | — |
| [Obtain unit of work by name](operations/obtain-unit-of-work-by-name.md) | Resolve named options and hand the caller a ready unit of work | Consumer calls `UnitOfWorkAccessor.UnitOfWork(key)` | `key` (options name) | `IUnitOfWork` instance | [BR-NH-04](business-rules.md#br-nh-04-non-empty-connection-string-required) | — | — |
| [Create unit of work](operations/create-unit-of-work.md) | Build (or reuse) a session factory and hand out a new unit of work | `UnitOfWorkFactory.GetUnitOfWork(options)` is called | `UnitOfWorkOptions` | `IUnitOfWork` instance | [BR-NH-04](business-rules.md#br-nh-04-non-empty-connection-string-required), [BR-NH-05](business-rules.md#br-nh-05-session-factories-cached-by-connection-string), [BR-NH-06](business-rules.md#br-nh-06-inhconfiguration-wrapper-cached-by-name-but-wrapped-nhibernate-configuration-rebuilt-per-cache-miss) | — | — |
| [Build session factory](operations/build-session-factory.md) | Build an NHibernate `Configuration`/`ISessionFactory` for a given engine and mapping set | First `GetUnitOfWork` call for a connection string/name pair | `UnitOfWorkOptions`, mapping assemblies | Cached `ISessionFactory`; `INhConfiguration` wrapper (cached), wrapped `Configuration` (rebuilt per call) | [BR-NH-06](business-rules.md#br-nh-06-inhconfiguration-wrapper-cached-by-name-but-wrapped-nhibernate-configuration-rebuilt-per-cache-miss), [BR-NH-07](business-rules.md#br-nh-07-unrecognized-database-type-falls-back-to-oracle), [BR-NH-08](business-rules.md#br-nh-08-fluent-and-hbm-mappings-both-loaded) | — | — |
| [Open session](operations/open-session.md) | Choose a stateful or stateless NHibernate session and its system-date helper | `UnitOfWorkFactory` builds a new unit of work | `ISessionFactory`, `options.StatelessSessionStrategy`, `options.Database` | `ISessionStrategy` + `ISessionHelper` pair | [BR-NH-09](business-rules.md#br-nh-09-sql-debug-interceptor-applies-only-to-stateful-sessions-while-debugging), [BR-NH-10](business-rules.md#br-nh-10-session-type-selected-by-statelesssessionstrategy-option) | — | — |
| [Begin transaction](operations/begin-transaction.md) | Start a `ReadCommitted` transaction on the unit of work's session | Consumer calls `IUnitOfWork.Begin()` | — | Active transaction, or exception | [BR-NH-11](business-rules.md#br-nh-11-transactions-always-use-readcommitted-isolation), [BR-NH-12](business-rules.md#br-nh-12-begin-refused-while-a-transaction-is-active) | — | [SQL-004](sql/SQL-004-test-connection.md) (as part of Test connection) |
| [Commit](operations/commit.md) | Commit the active transaction and clear the session | Consumer calls `IUnitOfWork.Commit()` | — | Committed transaction, cleared session, or exception | [BR-NH-13](business-rules.md#br-nh-13-commit-requires-an-active-transaction) | — | [SQL-004](sql/SQL-004-test-connection.md) (as part of Test connection) |
| [Rollback](operations/rollback.md) | Roll back any active transaction and dispose the session when rollback itself does not throw | Consumer calls `IUnitOfWork.Rollback()` | — | Rolled-back transaction (if any), disposed session (normal path only) | [BR-NH-14](business-rules.md#br-nh-14-rollback-disposes-the-session-only-when-rollback-itself-does-not-throw) | — | — |
| [Dispose unit of work](operations/dispose-unit-of-work.md) | Release the underlying NHibernate session | Consumer calls/`using`-disposes `IUnitOfWork` | — | Disposed session | — | — | — |
| [Repository CRUD and query operations](operations/repository-crud-query.md) | Add/update/delete/query/get/load entities through the active session strategy | Consumer calls `IRepository<TEntity>` members | Entity instance or id, or a LINQ expression | Persisted change, or query result | [BR-NH-15](business-rules.md#br-nh-15-add-update-and-load-vary-by-session-strategy) | [TEntity](database-tables.md#tentity) | [SQL-004](sql/SQL-004-test-connection.md) |
| [Get database system date](operations/get-database-system-date.md) | Read the current database server date for the active engine | Consumer reads `IRepository<T>.SystemDate`/`ISessionHelper.SystemDate` | — | `DateTime` (server date, or local fallback) | [BR-NH-17](business-rules.md#br-nh-17-systemdate-comes-from-the-database-server), [BR-NH-18](business-rules.md#br-nh-18-systemdate-falls-back-to-local-time-on-sentinel-values) | [DUAL](database-tables.md#dual) | [SQL-001](sql/SQL-001-oracle-system-date.md), [SQL-002](sql/SQL-002-postgresql-system-date.md), [SQL-003](sql/SQL-003-sql-server-system-date.md) |
| [Test connection](operations/test-connection.md) | Prove connectivity, session-factory build, and mapped-table accessibility for a generic entity | Consumer calls `IUnitOfWork.TestConnection<TEntity>()` | `TEntity` type parameter | Success (no rows), or exception | [BR-NH-11](business-rules.md#br-nh-11-transactions-always-use-readcommitted-isolation), [BR-NH-12](business-rules.md#br-nh-12-begin-refused-while-a-transaction-is-active), [BR-NH-13](business-rules.md#br-nh-13-commit-requires-an-active-transaction) | [TEntity](database-tables.md#tentity) | [SQL-004](sql/SQL-004-test-connection.md) |
| [Debug SQL tracing](operations/debug-sql-tracing.md) | Trace generated SQL to `System.Diagnostics.Trace` while debugging a stateful session | NHibernate prepares a statement on a stateful session built with `debugOutputSql = true` | Prepared `SqlString` | Trace output (only while a debugger is attached) | [BR-NH-09](business-rules.md#br-nh-09-sql-debug-interceptor-applies-only-to-stateful-sessions-while-debugging) | — | — |

## Process flow diagram

The following diagram visualizes the primary operational flow across operations, from registration through a typical unit-of-work lifecycle.

```mermaid
flowchart TD
	Register["Register NHibernate services<br>(AddNhibernateServices)"] --> ConfigureOptions["Configure named<br>unit-of-work options"]
	ConfigureOptions --> Obtain["Obtain unit of work<br>by name"]
	Obtain --> Create["Create unit of work<br>(factory)"]
	Create --> BuildFactory{"Session factory<br>cached?"}
	BuildFactory -->|No| Build["Build session factory"]
	BuildFactory -->|Yes| OpenSession["Open session<br>(choose strategy)"]
	Build --> OpenSession
	OpenSession --> Begin["Begin transaction"]
	Begin --> Work["Repository CRUD / query operations"]
	Work --> Decision{"Operation<br>succeeded?"}
	Decision -->|Yes| Commit["Commit"]
	Decision -->|No| Rollback["Rollback"]
	Commit --> Dispose["Dispose unit of work"]
	Rollback --> Dispose
```

## Database interactions

The following table summarizes which operations read from or write to the database. Per-step SQL and table citations live in each operation's detail page under `operations/`.

| Operation | SQL | Tables | Type |
| --- | --- | --- | --- |
| [Begin transaction](operations/begin-transaction.md) | [SQL-004](sql/SQL-004-test-connection.md) (as part of Test connection) | — | — |
| [Commit](operations/commit.md) | [SQL-004](sql/SQL-004-test-connection.md) (as part of Test connection) | — | — |
| [Repository CRUD and query operations](operations/repository-crud-query.md) | [SQL-004](sql/SQL-004-test-connection.md) (illustrative LINQ shape) | [TEntity](database-tables.md#tentity) | Read / Write (consumer-dependent) |
| [Get database system date](operations/get-database-system-date.md) | [SQL-001](sql/SQL-001-oracle-system-date.md), [SQL-002](sql/SQL-002-postgresql-system-date.md), [SQL-003](sql/SQL-003-sql-server-system-date.md) | [DUAL](database-tables.md#dual) (Oracle only) | Read |
| [Test connection](operations/test-connection.md) | [SQL-004](sql/SQL-004-test-connection.md) | [TEntity](database-tables.md#tentity) | Read |

All other operations (register services, configure options, obtain/create/dispose a unit of work, open a session, debug SQL tracing) manage infrastructure only and contain no literal SQL text authored by this library; see the [SQL catalog](sql/index.md) and [database tables](database-tables.md) for full detail on the statements above. This is distinct from [Commit](operations/commit.md) and [Rollback](operations/rollback.md): although neither contains SQL text in this library's own source, `Commit` calls NHibernate's `ITransaction.Commit()` — which internally issues a database `COMMIT` and, for a **stateful** session, triggers NHibernate's auto-flush of any pending INSERT/UPDATE/DELETE changes before committing, subject to the session's own externally-configured `FlushMode` (for example `FlushMode.Never`/`Manual` would suppress the implicit flush) — this is not an unconditional guarantee independent of session configuration. For a **stateless** session there is no such flush step, because stateless `Add`/`Update`/`Delete` operations already execute immediately rather than being queued; `Session.Clear()` after commit is a first-level-cache discard on a stateful session and a literal no-op on a stateless session. `Rollback` calls `ITransaction.Rollback()`, issuing a database `ROLLBACK`, when a transaction is active. These are NHibernate/ADO.NET provider behaviors external to this library's own source code, so "no SQL text in this library's source" must not be read as "no database activity occurs."*

## Failure and edge-case behavior
- Resolving an unregistered options name yields default `UnitOfWorkOptions` with no connection string, so [Create unit of work](operations/create-unit-of-work.md) throws `InvalidOperationException`.
- A `GetConnectionString()` failure in a consumer's `ConfigureUnitOfWorkOptions` subclass surfaces when the named options are first resolved, before any session work begins.
- Calling [Begin transaction](operations/begin-transaction.md) while the unit of work's transaction is still active throws `InvalidOperationException`. After a successful [Commit](operations/commit.md), the session stays open, and against NHibernate 5.2.7 a further `Begin` on the same unit of work starts a new transaction. [Rollback](operations/rollback.md) disposes the session, so what happens on a later `Begin` is not confirmed by this library's source. Using one unit of work per transaction is recommended, but the library does not enforce it.
- When `Rollback`'s own `transaction.Rollback()` call does not throw, [Rollback](operations/rollback.md) disposes the session; whether the unit of work can still be used afterward is not fully guaranteed either way (the stateful session strategy can transparently reopen a closed session on next access — see [ISessionStrategy](api/SAIF.NetCore.NHibernate.Interfaces/ISessionStrategy.md)). `Rollback` has no `try`/`finally`, so a throwing `transaction.Rollback()` skips that disposal (see the Rollback page for the full caveat). Disposal of an open transaction/session by some ADO.NET providers can itself trigger an implicit rollback — this is inferred provider behavior, not confirmed in this library's own source.*

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Business rules](business-rules.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [Service registration](service-registration.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Sources
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Extensions/IServicesCollectionExtensions.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Options/ConfigureUnitOfWorkOptions.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWorkAccessor.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Factories/UnitOfWorkFactory.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Factories/Configuration/BaseConfiguration.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWork.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Repository.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionHelpers/SessionHelperBase.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Factories/Configuration/SqlDebugOutputInterceptor.cs`
