---
title: SQL-004 Test connection
summary: Generic, always-empty connectivity probe inferred from UnitOfWork.TestConnection<TEntity>().
status: draft
owner: Framework
last_reviewed: 2026-10-02
library: SAIF.NetCore.NHibernate
reference_type: package
---

# SQL-004 Test connection

`UnitOfWork.TestConnection<TEntity>()` proves database connectivity, session-factory build success, and the mapped table's existence/accessibility by running a bounded, always-empty LINQ query against a consumer-supplied entity type inside its own transaction. No rows are ever returned; only success or a thrown exception matters.

## Classification

| Field | Value |
| --- | --- |
| **SQL ID** | SQL-004 |
| **Operation type** | Read |
| **Execution method** | ORM (NHibernate LINQ) |
| **Database** | Oracle / SQL Server / PostgreSQL (engine-neutral — identifier quoting and dialect vary by `options.Database`) |
| **Schema** | Unresolved** — `TEntity` is a generic type parameter; the table/schema come from the consumer's `ClassMap<TEntity>` |
| **Command type** | N/A (ORM-generated) |
| **Business object** | `UnitOfWork` |
| **Criteria property** | N/A — ORM |
| **Lifecycle method** | `UnitOfWork.TestConnection<TEntity>()` |

## Parameters

This statement has no parameters. The `Where(x => false)` predicate is a literal constant expression, so NHibernate's LINQ provider generates no bind variable for it.

## Tables

| Table | Role |
| --- | --- |
| [TEntity](../database-tables.md#tentity) | Source — unresolved, consumer-supplied generic entity; every column loaded by the consumer's `ClassMap<TEntity>`. |

## LINQ statement

Source: `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWork.cs:24`. The queryable is obtained one line earlier via `Repository<TEntity>.Query()` (`src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Repository.cs:41-44`).

```csharp
// src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Repository.cs:41-44
public IQueryable<TEntity> Query()
{
    return Session.Query<TEntity>();
}

// src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/UnitOfWork.cs:21-26
public void TestConnection<TEntity>()
{
    this.Begin();
    this.GetRepository<TEntity>().Query().Where(x => false).ToList();
    this.Commit();
}
```

## Sample SQL

> **Inferred SQL:** This SQL was inferred from the LINQ statement above and the NHibernate mappings. It is not concrete SQL from source code; NHibernate generates the executed statement at runtime, so aliases, column order, join syntax, and bind-parameter names may differ.

```sql
-- Inferred from LINQ (NHibernate mapping translation); not concrete SQL
SELECT
  T.*  -- unresolved mapping: TEntity (every column of the consumer's ClassMap<TEntity>)
FROM
  TEntity T  -- unresolved mapping: TEntity (table from the consumer's ClassMap<TEntity>)
WHERE
  1 = 0
```

Translation notes:
- Unresolved mapping (by design): the library is generic over `TEntity`, so no table or column can be resolved from this repository. `T.*` stands for "every column the consumer mapping loads" (identity/composite-key, version, `Map`, `References` FK, and `Component` columns, in mapping order). No column name has been invented.
- Illustration with the library's own test binding `TestConnection<Dual>()` (test project only, not shipped; `DualMapping`: `Table("dual")`, `Id(x => x.Dummy).Column("Dummy")`): the statement resolves to `SELECT D.Dummy FROM dual D WHERE 1 = 0` on Oracle.
- Constant predicate (version-dependent): NHibernate's LINQ provider renders the constant `false` lambda as an always-false predicate; the exact literal form (for example `1 = 0` or `0 = 1`) depends on the resolved NHibernate version, which is not pinned.*
- Materialization: `ToList()` is the materialization point. The result is discarded, and no operators run after it.
- Engine-neutral: the statement shape is identical on Oracle, SQL Server, and PostgreSQL; only identifier quoting and dialect differ, chosen by `options.Database`.
- Session strategy: the same SQL is issued under both stateful and stateless strategies (`Query<T>()` on `ISession`/`IStatelessSession`). Because the session is cleared first and holds no dirty entities, the stateful `Commit()` flush issues no DML.*

## Operations and processes
- [Test connection](../operations/test-connection.md)
- [Begin transaction](../operations/begin-transaction.md)
- [Commit](../operations/commit.md)
- [Repository CRUD and query operations](../operations/repository-crud-query.md)
- [Build session factory](../operations/build-session-factory.md)

## Business rules
- [BR-NH-01](../business-rules.md#br-nh-01-mapping-assemblies-fixed-at-registration)
- [BR-NH-04](../business-rules.md#br-nh-04-non-empty-connection-string-required)
- [BR-NH-08](../business-rules.md#br-nh-08-fluent-and-hbm-mappings-both-loaded)
- [BR-NH-11](../business-rules.md#br-nh-11-transactions-always-use-readcommitted-isolation)
- [BR-NH-12](../business-rules.md#br-nh-12-begin-refused-while-a-transaction-is-active)
- [BR-NH-13](../business-rules.md#br-nh-13-commit-requires-an-active-transaction)

> **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/UnitOfWork.cs`
- `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Repository.cs`
