---
title: Register NHibernate services
summary: Registers the singleton unit-of-work factory and scoped accessor with the DI container.
status: draft
owner: Framework
last_reviewed: 2026-10-02
library: SAIF.NetCore.NHibernate
reference_type: package
operation_id: OP-NH-01
trigger: Host application calls AddNhibernateServices or AddNhibernateServices<T> during startup
---

# Register NHibernate services

This operation wires the library's modern DI surface into a consuming application's `IServiceCollection`, so that `UnitOfWorkAccessor` can later be injected and used to obtain units of work.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-NH-01 |
| **Trigger** | Host calls `services.AddNhibernateServices(assemblyMappings, debugOutputSql)` or `services.AddNhibernateServices<T>(debugOutputSql)` at startup |
| **Inputs** | `assemblyMappings` (or a marker type `T`), `debugOutputSql` |
| **Outputs** | `IUnitOfWorkFactory` singleton, `UnitOfWorkAccessor` scoped service |
| **Primary components** | `IServicesCollectionExtensions.AddNhibernateServices`, `AddUnitOfWorkFactory` |
| **Entry point** | `src/SAIF.NetCore.Nhibernate/SAIF.NetCore.NHibernate/SAIF.NetCore.NHibernate/Extensions/IServicesCollectionExtensions.cs` |

## Steps

1. `AddNhibernateServices<T>(bool debugOutputSql = false)` resolves a single mapping assembly via `Assembly.GetAssembly(typeof(T))` and forwards to the `IEnumerable<Assembly>` overload. Call this overload directly instead when more than one mapping assembly must be scanned.
2. The internal `AddUnitOfWorkFactory(assemblyMappings, debugOutputSql)` registers `AddSingleton<IUnitOfWorkFactory>(provider => new UnitOfWorkFactory(assemblyMappings, debugOutputSql))`. The mapping assemblies and `debugOutputSql` flag are captured in this closure for the lifetime of the singleton ([BR-NH-01](../business-rules.md#br-nh-01-mapping-assemblies-fixed-at-registration)).
3. `AddNhibernateServices` then registers `AddScoped<UnitOfWorkAccessor>()`.
4. It returns `services` to support fluent chaining.
   - It does not call `AddOptions()`, register any `IConfigureOptions<UnitOfWorkOptions>`, or register `IUnitOfWork` directly — the consumer must register its own `ConfigureUnitOfWorkOptions` subclass (see [Configure named unit-of-work options](configure-named-unit-of-work-options.md)).
   - Calling `AddNhibernateServices` twice adds duplicate registrations; the last registration wins at resolution.*

## Process flow

The diagram below visualizes the generic-overload assembly-resolution branch and the two DI registrations that follow it.

```mermaid
flowchart TD
	Start([Host calls AddNhibernateServices]) --> Resolve{"Generic overload?"}
	Resolve -->|Yes| GetAssembly["Assembly.GetAssembly(typeof(T))"]
	Resolve -->|No| UseGiven["Use supplied assemblyMappings"]
	GetAssembly --> RegisterFactory["AddSingleton IUnitOfWorkFactory"]
	UseGiven --> RegisterFactory
	RegisterFactory --> RegisterAccessor["AddScoped UnitOfWorkAccessor"]
	RegisterAccessor --> Return([Return services])
```

## Failure and edge-case behavior
- Calling `AddNhibernateServices` more than once registers the singleton factory multiple times; the container resolves the last registration.*
- No exception is thrown at registration time even if `assemblyMappings` is empty or contains no mapped types — failures surface later, at session-factory build time.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Service registration](../service-registration.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/Extensions/IServicesCollectionExtensions.cs`
