Skip to content

Configuration settings

This library reads no configuration keys of its own — a search of every source file found no IConfiguration, GetSettingValue, GetSecureSetting, HasSetting, ConfigurationManager, or Environment.GetEnvironmentVariable usage. Instead, it exposes a consumer-facing configuration surface: the named-options POCO UnitOfWorkOptions (with non-trivial defaults), the abstract configurer ConfigureUnitOfWorkOptions that each consuming application subclasses once per logical database, and two registration parameters on AddNhibernateServices.

Configuration retrieval methods

Method Class / Interface Namespace Usage pattern
Named options type UnitOfWorkOptions SAIF.NetCore.NHibernate.Options POCO with seven settable properties; its parameterless constructor applies the library defaults. One named instance describes one logical database connection.
Abstract named-options configurer ConfigureUnitOfWorkOptions : IConfigureNamedOptions<UnitOfWorkOptions> SAIF.NetCore.NHibernate.Options The consumer subclasses it and registers it with services.ConfigureOptions<TSubclass>(). The subclass must implement UniqueName, Database, and GetConnectionString(). GetConnectionString() is called from the base class's constructor (this._connectionString = GetConnectionString();) — a virtual/abstract call executing before the derived class's own constructor body runs. If the override depends on fields the derived constructor itself assigns, those fields are not yet initialized when GetConnectionString() runs, so it can read nulls/defaults instead of intended values; do not have GetConnectionString() depend on derived-constructor-assigned state.
Engine selector DatabaseType enum SAIF.NetCore.NHibernate.Options Oracle = 0, Sql = 1, PostGreSql = 2.
Registration parameters IServicesCollectionExtensions.AddNhibernateServices(IEnumerable<Assembly>, bool) / AddNhibernateServices<T>(bool) SAIF.NetCore.NHibernate.Extensions Code-level settings, fixed at registration time and passed to the singleton UnitOfWorkFactory constructor.
Options resolution IOptionsSnapshot<UnitOfWorkOptions>.Get(name) Microsoft.Extensions.Options UnitOfWorkAccessor.UnitOfWork(key) resolves the named options on every call; it is scoped.

The library itself makes no IEnvironmentClient member calls, no IConfiguration reads, and no environment-variable reads. It only injects IEnvironmentClient/IDBConnectionClient so that consumer subclasses can call them inside their own GetConnectionString() override.

Library-exposed settings — UnitOfWorkOptions named options

One named instance exists per ConfigureUnitOfWorkOptions subclass; the name is the subclass's UniqueName.

# Property Type Library default Who sets it NHibernate / runtime effect When it takes effect
UO1 Name string "default" Library, in ConfigureUnitOfWorkOptions.Configure (= UniqueName) Key of the per-factory NHibernate configuration cache; copied to IUnitOfWork.Name. Every resolution
UO2 Database DatabaseType Oracle Consumer subclass's abstract Database property Selects engine configuration (OracleConfiguration/SqlConfiguration/PostGreSqlConfiguration) and the SystemDate session helper. An unrecognized value falls back to Oracle (BR-NH-07) Engine configuration: first build per name (cached). Session helper: every unit of work.
UO3 ConnectionString string null (no default) Consumer subclass's abstract GetConnectionString(), called once from the base constructor and cached NHibernate connection.connection_string; key of the static, process-wide session-factory cache. Required — GetUnitOfWork throws InvalidOperationException when null/empty (BR-NH-04). Contains credentials. First build per connection string (cached for process lifetime)
UO4 BatchSize int 20 Consumer override only (not set by the library's configurer) NHibernate adonet.batch_size First build per session-factory key only
UO5 ShowSql bool true Consumer override only NHibernate show_sql — echoes every generated SQL statement to stdout First build per session-factory key only
UO6 DriverFormatSql bool true Consumer override only FluentNHibernate .FormatSql() on the driver configurer (pretty-printed, multi-line SQL output) First build per session-factory key only
UO7 StatelessSessionStrategy bool false (stateful ISession) Consumer override only true selects IStatelessSession/StatelessSessionStrategy; false selects ISession/StatefulSessionStrategy (BR-NH-10) Every unit of work (read per GetUnitOfWork call, not cached)

Caching caveat: UO4–UO6 are captured only when the session factory is first built for a given connection string, and that factory is cached process-wide. Changing these options after the first unit of work has no effect until the process restarts, and two named instances sharing a connection string also share the first one's BatchSize/ShowSql/DriverFormatSql.* UO7 and the session-helper part of UO2 are evaluated on every call. Nested-cache mismatch: UO3's session-factory cache (keyed by ConnectionString) and the underlying engine-Configuration cache (keyed by Name, see Build session factory) are two separate caches with different keys. If two calls share the same Name but supply different ConnectionString values, a new session factory IS built (connection-string cache miss), but the reused, name-keyed Configuration object's ConnectionString field still holds the FIRST connection string ever seen for that Name — so the newly built factory silently connects using the OLD connection string rather than the one just supplied. A new connection-string key does not, by itself, guarantee that the new connection string is actually used end-to-end.

Registration parameters

Parameter Method Type Default Effect
assemblyMappings AddNhibernateServices(IEnumerable<Assembly>, bool) IEnumerable<Assembly> none (required) Assemblies scanned for both Fluent ClassMap<T> and embedded HBM mappings; fixed for the lifetime of the singleton factory.
T AddNhibernateServices<T>(bool) type parameter — Assembly.GetAssembly(typeof(T)) — resolves to a single mapping assembly.
debugOutputSql Both overloads bool false on the generic overload; required on the IEnumerable<Assembly> overload When true, stateful sessions open with SqlDebugOutputInterceptor, which traces SQL to Trace only while a debugger is attached. Stateless sessions never receive it. Independent of ShowSql.

Override mechanisms for UO4–UO7

Unless a consumer applies one of the mechanisms below, the library defaults apply — meaning SQL logging and SQL formatting are on.

Mechanism Example Scope
Override Configure in the subclass public override void Configure(string n, UnitOfWorkOptions o) { base.Configure(n, o); if (n == UniqueName) { o.ShowSql = false; } } That named database only
Register an additional named configure delegate services.Configure<UnitOfWorkOptions>("myname", o => o.ShowSql = false); That named database only
Apply to every named instance services.ConfigureAll<UnitOfWorkOptions>(o => o.ShowSql = false); All databases — can also overwrite Name/Database/ConnectionString if misused*
Bind from IConfiguration (consumer choice) services.Configure<UnitOfWorkOptions>("myname", Configuration.GetSection("NHibernate:myname")) The library supplies no section name or binding; any appsettings.json keys here are entirely consumer-defined
Construct UnitOfWorkOptions directly new UnitOfWorkOptions { Name = "test", Database = DatabaseType.Oracle, ConnectionString = "<provider-specific connection string>" } passed straight to UnitOfWorkFactory.GetUnitOfWork Bypasses the options pipeline entirely

Environment API settings

The library reads no Environment API keys itself. Every IEnvironmentClient key used with this library is consumer-defined inside the subclass's GetConnectionString() override. The rows below are illustrative examples from the test project, not library requirements.

Setting key (example) Method Secure Purpose Status
oracledatabase IEnvironmentClient.GetSettingValue(string) No Oracle instance name, passed to IDBConnectionClient.GetOracleConnection(instance, userName) Example (test-only, not shipped)
netframeworksqlserver4 GetSettingValue(string) No SQL Server host, passed to GetSqlServerConnection(server, instance, userName) Example (test-only)

Database connection configuration

The library is a connection-consumer framework: it defines no connection names or keys of its own. Each consumer defines one connection per ConfigureUnitOfWorkOptions subclass.

Element Value
Connection identity The subclass's UniqueName, which becomes the UnitOfWorkOptions name
Connection-string source The consumer's GetConnectionString() override — the standard pattern calls IDBConnectionClient.GetOracleConnection/GetSqlServerConnection/GetPostgreSqlServerConnection
Providers Oracle: Oracle.ManagedDataAccess.Core via OracleManagedDataClientDriver (no native client install needed). SQL Server: NHibernate's default MsSql2008 driver. PostgreSQL: Npgsql via NpgsqlDriver*
Resolution timing Once per configurer construction (base constructor) — in practice once per IOptionsSnapshot scope, i.e. once per request*
Caching Session factory cached process-wide, keyed by the connection string itself; but the nested, name-keyed Configuration cache can reuse a stale connection string if Name collides with a different ConnectionString — see the caching caveat above and Build session factory.

Secure settings

The library reads no secure settings itself. Connection strings (UO3) are secrets but are not configuration keys the library retrieves directly — they are produced by the consumer's GetConnectionString() and then held in UnitOfWorkOptions.ConnectionString, in each configurer's private cached field, and as the key of the static SessionFactories dictionary for the life of the process.

Transitive configuration (from dependencies)

Settings a consuming application must supply when it follows the standard ConfigureUnitOfWorkOptions pattern; the library itself has no ProjectReferences.

Setting / service Kind Required Source dependency Notes
IEnvironmentClient registration Required service (not registered by this library) Yes — the configurer constructor requires it SAIF.NetCore.ServiceContracts (contract); SAIF.NetCore.EnvironmentClient (implementation) Usually registered by SAIF.NetCore.ServiceExtensions (CoreAPIStartup). The full bootstrap-key catalog (which keys are mandatory vs. optional, and how the process resolves them) is documented on the owning library's own page: SAIF.NetCore.EnvironmentClient configuration. In summary for this library's own usage: the OS process environment variable EnvironmentApiUrl is mandatory for every host (read once, before the client's constructor body, independent of IConfiguration) — without it, IEnvironmentClient construction fails with MissingEnvironmentUrlVariableException and the consumer's ConfigureUnitOfWorkOptions subclass constructor cannot complete. AppSettings:ApplicationHost/AppSettings:EnvApiDeveloperOverrideAllowed/AppSettings:EnvApiDeveloperSettingsOverride are developer-machine-only optional overrides with no effect on non-developer hosts. When the registered implementation is SecureEnvironmentClient, its constructor requires COREAPIENABLED == "1" or a developer-machine host (IsDeveloperMachine()) merely to construct — this gate is evaluated unconditionally at construction time, regardless of whether any later call through this client resolves a secure or non-secure setting; a non-developer host that fails the gate cannot construct the client at all, so this library's ConfigureUnitOfWorkOptions subclass constructor cannot complete either. Registering a different, non-secure IEnvironmentClient implementation avoids this gate entirely — that is a different implementation choice, not a case of the secure client "only mattering" when secure settings are read.
IDBConnectionClient registration Required service Yes (constructor) SAIF.NetCore.ServiceContracts (contract); SAIF.NetCore.DBConnectionClient (implementation) Usually registered by SAIF.NetCore.ServiceExtensions. The full endpoint-key catalog is documented on the owning library's own page: SAIF.NetCore.DBConnectionClient configuration. In summary for this library's own usage: ConnectionClient.Setup() reads DBConnectionClient:ServiceUrl, DBConnectionClient:SqlConnectionEndpoint, DBConnectionClient:PostgreSqlConnectionEndpoint, and DBConnectionClient:OracleConnectionEndpoint unconditionally and sequentially, inside the constructor, regardless of which DatabaseType the consumer later uses — there is no engine branch at construction time. This is distinct from later, engine-specific usage: only the matching GetOracleConnection/GetSqlServerConnection/GetPostgreSqlServerConnection call that this library's subclasses actually invoke at runtime uses the corresponding endpoint value.
IOptionsSnapshot<UnitOfWorkOptions> / options infrastructure Required service Yes Host (ASP.NET Core / Generic Host registers AddOptions by default) Used by UnitOfWorkAccessor
DBConnectionClient:ServiceUrl, DBConnectionClient:OracleConnectionEndpoint, DBConnectionClient:SqlConnectionEndpoint, DBConnectionClient:PostgreSqlConnectionEndpoint Environment API Required unconditionally at construction SAIF.NetCore.DBConnectionClient All four keys are read by the ConnectionClient constructor for every host, independent of which DatabaseType engine is actually used afterward
dbconnectionclient:connectionservicecreds Secure Environment API setting Required when ServiceExtensions.RegisterDBConnectionClient registers the client SAIF.NetCore.ServiceExtensions —

Configuration dependencies

Dependency Type Required at Impact if missing
A ConfigureUnitOfWorkOptions subclass registered for a given name Code/DI Startup, resolved at first use A UnitOfWorkAccessor.UnitOfWork(key) call for an unregistered name yields default options with no connection string, which throws InvalidOperationException on GetUnitOfWork
IEnvironmentClient / IDBConnectionClient registration DI service Startup The consumer subclass's constructor fails to resolve, which fails DI container validation/first resolution
Valid connection-string resolution in GetConnectionString() Runtime First options resolution per name An exception there surfaces when the options are first resolved, before any session work begins

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Options/UnitOfWorkOptions.cs
  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Options/ConfigureUnitOfWorkOptions.cs
  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Options/DatabaseType.cs
  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Extensions/IServicesCollectionExtensions.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/UnitOfWorkAccessor.cs
  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate.Tests/Options/ConfigureOracleUnitOfWork.cs (test-fixture example of a ConfigureUnitOfWorkOptions subclass)
  • src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate.Tests/Options/ConfigureSqlUnitOfWork.cs (test-fixture example of a ConfigureUnitOfWorkOptions subclass)