Get database system date¶
This operation provides a database-sourced "now" for consumers that need the server's clock rather than the application server's clock — for example, for audit timestamps.
| Field | Value |
|---|---|
| Operation ID | OP-NH-12 |
| Trigger | Consumer reads IRepository<TEntity>.SystemDate (which reads ISessionHelper.SystemDate) |
| Inputs | — |
| Outputs | A DateTime from the database server, or the application server's local time as a fallback |
| Primary components | SessionHelperBase.SystemDate, OracleSessionHelper, SqlServerSessionHelper, PostgreSqlSessionHelper |
| Entry point | src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionHelpers/SessionHelperBase.cs |
Steps¶
SessionHelperBase.SystemDaterunsSession.CreateSqlQuery(DateSql).UniqueResult()every time it is read — there is no caching (BR-NH-17)DateSqlis set by the concrete subclass constructor: SQL-001 forOracleSessionHelper, SQL-002 forPostgreSqlSessionHelper, SQL-003 forSqlServerSessionHelper.- Convert the raw query result with
Convert.ToDateTime(sysDate). - If the converted result equals
DateTime.MinValueorDateTime.MaxValue: returnDateTime.Now(application server local time) instead (BR-NH-18) - Otherwise: return the converted database result.
PostgreSQL caveat:
PostgreSqlSessionHelper.DateSqlisSelect current_date, which returns a DATE-only value (midnight, no time-of-day component) — unlike Oracle'ssysdateand SQL Server'sGetDate(), which both return full date+time. Consumers relying onSystemDatefor audit timestamps that need time-of-day precision should not use the PostgreSQL engine helper for that purpose.
Note: SessionHelperBase also exposes a UseDatabaseForSystemDate property, set in the constructor but never read anywhere else in the class or in the SystemDate getter — it is a confirmed-unused flag, not merely suspected to be unused.
The fallback is narrowly scoped: it triggers only when Convert.ToDateTime(sysDate) succeeds and the resulting value equals exactly DateTime.MinValue or DateTime.MaxValue. A failed conversion (for example a malformed or unexpected query result) or a query/connectivity exception is not caught anywhere in SystemDate and propagates to the caller unhandled.
Process flow¶
The diagram below visualizes the query/conversion steps and the sentinel-value branch that decides between the database result and the local-time fallback.
flowchart TD
Start(["SystemDate read"]) --> RunQuery["CreateSqlQuery(DateSql).UniqueResult()"]
RunQuery --> Convert["Convert.ToDateTime(result)"]
Convert --> Sentinel{"MinValue or<br>MaxValue?"}
Sentinel -->|Yes| Fallback(["Return DateTime.Now"])
Sentinel -->|No| ReturnDb(["Return database result"])
Failure and edge-case behavior¶
- A database connectivity failure during the query surfaces as whatever exception NHibernate/the ADO.NET driver raises; there is no try/catch around the query itself.
- A
NULL/sentinel result from the database is masked by the local-time fallback rather than raised as an error, which can hide real data problems.* - The
UseDatabaseForSystemDateproperty is confirmed dead/unused state in the current implementation: it is assigned in the constructor but never read bySystemDateor anywhere else in the class. - On PostgreSQL specifically, when the query returns a successful, non-sentinel result,
SystemDatereturns midnight (date-only); this is a property of thecurrent_dateSQL expression's successful result, not of the fallback logic. This "always midnight" characterization describes only that successful-result path — it does not describe the sentinel-fallback path (step 3 above), which instead returnsDateTime.Now(the application server's local time, including time-of-day), nor the unhandled-exception path for a query/conversion failure.
Related documentation¶
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/SessionHelpers/SessionHelperBase.cssrc/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionHelpers/OracleSessionHelper.cssrc/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionHelpers/SQLSessionHelper.cssrc/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/SessionHelpers/PostgreSqlSessionHelper.cs