---
title: Debug SQL tracing
summary: Writes every prepared SQL statement to System.Diagnostics.Trace, but only on stateful sessions while a debugger is attached.
status: draft
owner: Framework
last_reviewed: 2026-10-02
library: SAIF.NetCore.NHibernate
reference_type: package
operation_id: OP-NH-14
trigger: A stateful session is opened with debugOutputSql = true and a debugger is attached to the process
---

# 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

1. [Build session factory](build-session-factory.md) is configured with `debugOutputSql = true` (via `AddNhibernateServices`'s second parameter), and [Open session](open-session.md) opens a **stateful** session (`options.StatelessSessionStrategy == false`) ([BR-NH-09](../business-rules.md#br-nh-09-sql-debug-interceptor-applies-only-to-stateful-sessions-while-debugging)):
   - The session is opened with `factory.WithOptions().Interceptor(new SqlDebugOutputInterceptor()).OpenSession()` instead of a plain `factory.OpenSession()`.
2. Every time NHibernate prepares a statement to send to the database, it calls the interceptor's `OnPrepareStatement(SqlString sql)` override.
3. `OnPrepareStatement` checks `Debugger.IsAttached`:
   - If `true`: write `"{yyyy-MM-dd HH:mm:ss} - NHibernate: "` followed by the SQL text to `Trace`.
   - If `false`: skip writing; no output is produced even though the interceptor is attached.
4. 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`.

```mermaid
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 of `debugOutputSql`.
- 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 own `show_sql`/`format_sql` properties) are a separate, independent mechanism from this interceptor; both can be enabled or disabled independently.*

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Configuration](../configuration.md)
- [Open session](open-session.md)
- [Build session factory](build-session-factory.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/Factories/Configuration/SqlDebugOutputInterceptor.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Factories/UnitOfWorkFactory.cs`
