SAIF.Framework.Data.NHibernate operations and processes¶
This page catalogs the operations this library performs and, for each, the step-by-step logic that implements it.
Operation catalog¶
| Operation | Intent | Trigger | Inputs | Outputs | Rules | Tables | SQL |
|---|---|---|---|---|---|---|---|
| Build and cache an NHibernate configuration for a connection string | Build (or reuse a cached) NHibernate Configuration/ISessionFactory for a given connection string. |
IConfigurationFactory.GetConfiguration(connection, batchSize, showSql) |
Connection string, batch size, show-SQL flag | Cached PersistenceConfiguration |
— | — | — |
| Obtain a unit of work for a connection string | Build (or reuse a cached) ISessionFactory and hand back a NHibernateUnitOfWork bound to a fresh session. |
IUnitOfWorkFactory.GetUnitOfWork(connectionString, batchSize, showSql) |
Connection string, batch size, show-SQL flag | NHibernateUnitOfWork bound to a freshly opened ISession/IStatelessSession |
— | — | — |
| Unit of work transaction lifecycle | Manage the begin/commit/rollback lifecycle of a unit of work's transaction. | Consumer calls Begin()/Commit()/Rollback()/Dispose() on a NHibernateUnitOfWork |
— | Transaction committed or rolled back; session cleared or disposed | BR-001, BR-002 | — | — |
| Repository CRUD and query operations (stateful vs stateless divergence) | Perform generic persistence operations against a mapped entity, diverging by session strategy. | Consumer calls Add/Update/Delete/Query/Get/Load/SystemDate on a Repository<TEntity> |
Entity instance, entity ID, or none (for Query/SystemDate) |
Entity persisted/retrieved; behavior differs by session strategy | BR-003, BR-004 | — | SQL-004 |
| Oracle sequence based ID generation (Imaging domain) | Obtain the next value of an Oracle sequence directly, bypassing the mapped-entity ID-generation path. | Consumer calls GetNextImageId/GetNextTowId/GetNextImageAffiliationId extension methods |
IRepository<Image> / IRepository<ImageSystem> / IRepository<ImageAffiliation> instance |
long — next sequence value |
— | image, IMGSYS, IMAGE_AFFILIATION | SQL-001, SQL-002, SQL-003 |
Process flow diagram¶
The following diagram visualizes the primary operational flow from configuration through transaction commit.
flowchart TD
Start([Consumer requests unit of work]) --> Cfg[Build/cache NHibernate Configuration]
Cfg --> UoW["Build/cache ISessionFactory; open Session/StatelessSession"]
UoW --> Begin[Begin transaction]
Begin --> Ops[Repository Add/Update/Delete/Query/Get/Load]
Ops --> Decision{Success?}
Decision -->|Yes| Commit([Commit transaction])
Decision -->|No| Rollback([Rollback transaction])
Build and cache an NHibernate configuration for a connection string¶
A consumer requests an NHibernate Configuration for a connection string through IConfigurationFactory.GetConfiguration(connection, batchSize, showSql), typically invoked from UnitOfWorkFactoryBase.BuildSessionFactory.
| Field | Value |
|---|---|
| Trigger | IConfigurationFactory.GetConfiguration(connection, batchSize, showSql) call |
| Inputs | Connection string, batch size, show-SQL flag |
| Outputs | A cached PersistenceConfiguration (wraps NHibernate Configuration + a serialized-config file path) |
| Primary components | Factories/ConfigurationFactoryBase.cs, Factories/OracleConfigurationFactory.cs, Factories/SqlServerConfigurationFactory.cs |
Steps — Build and cache an NHibernate configuration for a connection string¶
- Look up
connectionin the staticConcurrentDictionary<string, PersistenceConfiguration> Configurations; if present, return it (cache hit). - On cache miss, call
CreateConfiguration(connection, batchSize, showSql). - Attempt to deserialize a previously-serialized
Configurationfrom a binary file at{assemblyDirectory}\{GetConfigurationFileName()}(Oracle.configorSqlServer.config) usingBinaryFormatter. - On any exception (including file-not-found): fall back to
null. - If no serialized configuration was found, build a new one via the engine-specific
GetNewConfiguration(formatSql)override, which configuresFluently.Configure()with the engine driver and scans this assembly (and anyClassMapAssemblyListassemblies) forClassMap<T>/.hbm.xmlmappings. - Set
Environment.ConnectionString,Environment.BatchSize,Environment.ShowSqlon the configuration. - Return a
PersistenceConfigurationwrapping the builtConfigurationand the serialized-config file path.
Failure and edge-case behavior — Build and cache an NHibernate configuration for a connection string¶
- Deserialization failures are silently swallowed (caught
Exception, configuration set tonull, forcing a fresh build).
Obtain a unit of work for a connection string¶
A consumer requests a NHibernateUnitOfWork bound to a freshly opened session through IUnitOfWorkFactory.GetUnitOfWork(connectionString, batchSize, showSql).
| Field | Value |
|---|---|
| Trigger | IUnitOfWorkFactory.GetUnitOfWork(connectionString, batchSize, showSql) |
| Inputs | Connection string, batch size, show-SQL flag |
| Outputs | A NHibernateUnitOfWork bound to a freshly opened ISession/IStatelessSession |
| Primary components | Factories/UnitOfWorkFactoryBase.cs, Factories/OracleUnitOfWorkFactory.cs, Factories/OracleStatelessUnitOfWorkFactory.cs, Factories/SqlServerUnitOfWorkFactory.cs |
Steps — Obtain a unit of work for a connection string¶
- Lock the static
SessionFactoriesdictionary (per-process synchronization). - Get-or-add an
ISessionFactoryforconnectionStringviaBuildSessionFactory, which resolves thePersistenceConfiguration(see Build and cache an NHibernate configuration for a connection string) and callsConfiguration.BuildSessionFactory(). - Call the engine-specific
CreateUnitOfWork(factory)override: OracleUnitOfWorkFactory/SqlServerUnitOfWorkFactory→CreateSessionUnitOfWork(statefulISessionviafactory.OpenSession(), wrapped inStatefulSessionStrategy).OracleStatelessUnitOfWorkFactory→CreateStatelessSessionUnitOfWork(IStatelessSessionviafactory.OpenStatelessSession(), wrapped inStatelessSessionStrategy).- Build the matching
ISessionHelper(OracleSessionHelper/SqlServerSessionHelper) viaBuildSessionHelper. - Return a new
NHibernateUnitOfWork(sessionStrategy, sessionHelper).
Unit of work transaction lifecycle¶
Once a consumer has obtained a NHibernateUnitOfWork, it manages the transaction boundary explicitly through Begin(), Commit(), and Rollback().
| Field | Value |
|---|---|
| Trigger | Consumer calls Begin() after obtaining a NHibernateUnitOfWork |
| Outputs | Transaction committed or rolled back; session cleared |
| Primary components | UnitOfWork/NHibernateUnitOfWork.cs |
Steps — Unit of work transaction lifecycle¶
Begin(): checkIsTransactionInProgress()(transactionIsActive,WasCommitted, orWasRolledBack).- If true: throw
InvalidOperationException("There is a transaction already in progress.")(BR-001). - Otherwise: call
Session.Clear()thenSession.BeginTransaction(IsolationLevel.ReadCommitted). - Repository operations (
Add/Update/Delete/Query/Get/Load) are performed via repositories obtained fromGetRepository<TEntity>(), all sharing this unit of work'sSession(BR-005). Commit(): get the currentITransaction.- If
!transaction.IsActive: throwInvalidOperationException("You must call Begin() on the unit of work before you can commit.")(BR-002). - Otherwise: call
transaction.Commit()thenSession.Clear(). Rollback(): if the transactionIsActive, calltransaction.Rollback(); then always callSession.Dispose().Dispose(): standard dispose pattern; if not already disposed andSessionis not null, callSession.Dispose().
Failure and edge-case behavior — Unit of work transaction lifecycle¶
Begin()andCommit()both enforce state invariants viaInvalidOperationException(BR-001, BR-002).Rollback()disposes the session unconditionally, even if no transaction was active.
Repository CRUD and query operations stateful vs stateless divergence¶
A consumer performs generic persistence operations against a mapped entity through a Repository<TEntity>; the underlying behavior diverges depending on whether the unit of work uses a stateful or stateless session strategy.
| Field | Value |
|---|---|
| Trigger | Consumer calls Add/Update/Delete/Query/Get/Load/SystemDate on a Repository<TEntity> |
| Outputs | Entity persisted/retrieved; behavior differs by session strategy |
| Primary components | Repositories/RepositoryBase.cs, Sessions/StatefulSessionStrategy.cs, Sessions/StatelessSessionStrategy.cs, SessionHelper/SessionHelperBase.cs |
Steps — Repository CRUD and query operations¶
RepositoryBase<TEntity>.Add(entity)→Session.Add(entity).- Stateful:
ISession.SaveOrUpdate(entity)(Sessions/StatefulSessionStrategy.cs). - Stateless:
IStatelessSession.Insert(entity)(Sessions/StatelessSessionStrategy.cs). RepositoryBase<TEntity>.Update(entity)(BR-003):- Stateful: no-op (empty method body in
StatefulSessionStrategy.Update, since dirty-checking auto-flushes on commit). - Stateless: explicit
IStatelessSession.Update(entity)call. RepositoryBase<TEntity>.Delete(entity)→Session.Delete(entity)in both strategies.RepositoryBase<TEntity>.Query()→Session.Query<TEntity>()(LINQ to NHibernate) in both strategies.RepositoryBase<TEntity>.Get(id)/Load(id):- Stateful:
ISession.Get<TEntity>(id)/ISession.Load<TEntity>(id)(lazy proxy). - Stateless: both
GetandLoaddelegate toIStatelessSession.Get<TEntity>(id)(no lazy-proxy support in stateless mode). RepositoryBase<TEntity>.SystemDate→SessionHelper.SystemDate(BR-004, SQL-004) → runs the engine-specific date SQL and falls back toDateTime.Nowif the result is null/min/max.
Failure and edge-case behavior — Repository CRUD and query operations¶
- No exceptions are raised by the CRUD/query steps themselves; the only fallback behavior is
SystemDate's local-clock substitution (BR-004).
Oracle sequence based ID generation Imaging domain¶
A consumer calls one of three extension methods to obtain the next value of an Oracle sequence directly, bypassing the mapped-entity ID-generation path.
| Field | Value |
|---|---|
| Trigger | Consumer calls GetNextImageId, GetNextTowId, or GetNextImageAffiliationId extension methods on IRepository<Image>/IRepository<ImageSystem>/IRepository<ImageAffiliation> |
| Outputs | long — next sequence value |
| Primary components | Repositories/Imaging/ImageRepositoryExtensions.cs |
Steps — Oracle sequence based ID generation, Imaging domain¶
- Cast the
IRepository<T>to the concreteRepository<T>to access its internalSession. - Run
Session.CreateSqlQuery("select {sequence}.nextval from dual")— direct SQL escape hatch (not entity-mapped), one of three: image_seq(SQL-001, image)tower_seq(SQL-002, IMGSYS)image_affiliation_seq(SQL-003, IMAGE_AFFILIATION)Convert.ToInt64(query.UniqueResult())and return.
Failure and edge-case behavior — Oracle sequence based ID generation, Imaging domain¶
- This is the one "direct SQL escape hatch" case in this library — session-level
CreateSqlQuery, Oracle-only (usesNEXTVAL FROM DUALsyntax). ImageAffiliation.Idalso has a native NHibernate sequence generator (GeneratedBy.Native("IMAGE_AFFILIATION_SEQ")), making SQL-003 a parallel/redundant ID-acquisition path to the mapping's own generator.*
Database interactions¶
The following table summarizes which operations read from or write to the database.
| Operation | SQL | Tables | Type |
|---|---|---|---|
| Repository CRUD and query operations (stateful vs stateless divergence) | SQL-004 | — (DUAL pseudo-table / no table) |
Read |
| Oracle sequence based ID generation (Imaging domain) | SQL-001, SQL-002, SQL-003 | image, IMGSYS, IMAGE_AFFILIATION | Read |
Cross-cutting failure behavior¶
- Deserialization of a previously-serialized
Configurationsilently swallows any exception and falls back to a fresh build, rather than surfacing the failure. Begin()/Commit()enforce state invariants viaInvalidOperationException(BR-001, BR-002);Rollback()disposes the session unconditionally.SystemDatesilently substitutes localDateTime.Nowwhen the database query returns null/min/max (BR-004).
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Related documentation¶
Sources¶
Factories/ConfigurationFactoryBase.csFactories/OracleConfigurationFactory.csFactories/SqlServerConfigurationFactory.csFactories/UnitOfWorkFactoryBase.csFactories/OracleUnitOfWorkFactory.csFactories/OracleStatelessUnitOfWorkFactory.csFactories/SqlServerUnitOfWorkFactory.csUnitOfWork/NHibernateUnitOfWork.csRepositories/RepositoryBase.csSessions/StatefulSessionStrategy.csSessions/StatelessSessionStrategy.csSessionHelper/SessionHelperBase.csRepositories/Imaging/ImageRepositoryExtensions.cs