Debug SQL tracing¶
This operation gives developers a way to see every SQL statement NHibernate actually sends to the database while debugging, without affecting production logging.
| Field | Value |
|---|---|
| Operation ID | OP-NH-14 |
| Trigger | AddNhibernateServices(assemblies, debugOutputSql: true) was used at registration and the current unit of work uses a stateful session and a debugger is attached to the process |
| Inputs | The prepared SqlString for each statement NHibernate sends |
| Outputs | A timestamped line written to System.Diagnostics.Trace for every prepared statement |
| Primary components | SqlDebugOutputInterceptor.OnPrepareStatement |
| Entry point | src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Factories/Configuration/SqlDebugOutputInterceptor.cs |
Steps¶
- Build session factory is configured with
debugOutputSql = true(viaAddNhibernateServices's second parameter), and Open session opens a stateful session (options.StatelessSessionStrategy == false) (BR-NH-09): - The session is opened with
factory.WithOptions().Interceptor(new SqlDebugOutputInterceptor()).OpenSession()instead of a plainfactory.OpenSession(). - Every time NHibernate prepares a statement to send to the database, it calls the interceptor's
OnPrepareStatement(SqlString sql)override. OnPrepareStatementchecksDebugger.IsAttached:- If
true: write"{yyyy-MM-dd HH:mm:ss} - NHibernate: "followed by the SQL text toTrace. - If
false: skip writing; no output is produced even though the interceptor is attached. - Return
base.OnPrepareStatement(sql)unchanged — the interceptor only observes/logs; it never rewrites the statement.
Process flow¶
The diagram below visualizes the stateful/debug-flag gate on whether the interceptor is attached at all, and the Debugger.IsAttached check inside OnPrepareStatement.
flowchart TD
Start(["Statement prepared"]) --> Interceptor{"Stateful session with<br>debugOutputSql = true?"}
Interceptor -->|No| NoTrace(["No interceptor attached — no tracing"])
Interceptor -->|Yes| OnPrepare["OnPrepareStatement(sql) called"]
OnPrepare --> DebuggerCheck{"Debugger.IsAttached?"}
DebuggerCheck -->|No| Skip(["No output written"])
DebuggerCheck -->|Yes| Write["Write timestamp + SQL to Trace"]
Write --> PassThrough(["Return sql unchanged"])
Failure and edge-case behavior¶
- Stateless sessions never receive this interceptor, so
TestConnection/queries run through a stateless unit of work produce no SQL trace output regardless ofdebugOutputSql. - Even with
debugOutputSql = true, no output appears unless a debugger is actually attached to the running process — this is not a general-purpose production logging mechanism. UnitOfWorkOptions.ShowSql/DriverFormatSql(NHibernate's ownshow_sql/format_sqlproperties) are a separate, independent mechanism from this interceptor; both can be enabled or disabled independently.*
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/Factories/Configuration/SqlDebugOutputInterceptor.cssrc/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Factories/UnitOfWorkFactory.cs