Batch NHibernate Write Statements to Cut Database Round-Trips
Configure NHibernate ADO.NET statement batching to reduce database round-trips during session flush, with verification and rollback steps.
10 Jul 2025, 09:10 UTC

Problem and useful takeaway
By default, NHibernate can send one database command for every INSERT, UPDATE, or DELETE statement during an ISession flush. If you save or modify dozens of entities in one transaction, the application makes dozens of round-trips to the database. This adds latency and can slow bulk write workloads even when the database itself is fast.
The useful takeaway is to enable NHibernate ADO.NET statement batching through the adonet.batch_size setting. Batching groups pending write DML from a single session flush into fewer database commands. It does not make the batch atomic, and it does not batch SELECT statements. You should verify the setting with SQL logging and a database profiler, and be ready to roll back the session and the configuration if the driver raises an exception.
Prerequisites
- An application that builds an NHibernate
ISessionFactoryfrom XML,appsettings, or fluent code. - Write permission to edit the application configuration file.
- A database user account with INSERT, UPDATE, and DELETE permissions on the target tables.
- Access to a database profiler or APM trace for the target database, such as SQL Server Profiler, PostgreSQL
pg_stat_statements, or an equivalent tool. - This guide assumes a current NHibernate release (5.x or later). Older versions may use different configuration keys or default behaviors.
Configure the batch size
Open the NHibernate configuration source used by your application. In XML configuration, add or edit the batch size property:
<property name="adonet.batch_size">20</property>
If your application uses appsettings.json or a fluent API, use the equivalent key for your configuration source. The exact key name can differ between XML, JSON, and code-based configuration, so confirm the key against your NHibernate version rather than copying from another project.
A value of 0 or a missing key typically disables batching. Positive values such as 20 or 50 are common starting points. The ideal size depends on the ADO.NET driver, average row size, and network latency.
Where to apply and required permissions
Edit the configuration file in the project or the configuration project that builds the ISessionFactory. Required permissions are file write access and permission to restart or rebuild the application. Expected check: the application starts without NHibernate configuration exceptions. Risk: an unrecognized key name is silently ignored, leaving batching disabled.
Apply the change
Save the configuration file and rebuild or restart the application so the new ISessionFactory picks up the setting. No database migration is required; this is a client-side NHibernate behavior.
Verify that batching is active
- Enable NHibernate SQL logging for your logging framework, such as
show_sqlor the equivalent logger for log4net, NLog, or Serilog. - Run a representative write workload: open one
ISession, begin a transaction, insert or modify multiple entities, then flush and commit. - Capture the database commands with a profiler or APM trace for the same workload before and after the change.
- Confirm that the number of command batches is lower than the number of write statements, and that no
NotSupportedExceptionor provider-specific batch error appears.
If the profiler still shows one command per statement, the driver may ignore the setting or the configuration key may not have taken effect. Check the application startup log for NHibernate configuration messages and verify the effective setting through your session factory’s settings API.
Diagnostic decision table
| Observation | Likely cause | Suggested action |
|---|---|---|
| Command count drops after enabling | Batching is working | Keep the value and monitor lock duration under load. |
| No change in command count | Key ignored, wrong key name, or driver does not support batching | Verify the configuration key for your NHibernate version; test a smaller value; disable if unsupported. |
| Exception during flush | Provider or NHibernate version does not support the requested batch size | Roll back the transaction, dispose the session, and revert adonet.batch_size to 0. |
| High memory use or long locks | Batch size too large for the workload | Reduce the batch size, for example to 10 or 20, and re-measure. |
Handle failed batches and roll back
A failed batched flush can surface as a single data provider exception that affects multiple pending entities. Because NHibernate may not know exactly which statement in the batch failed, do not reuse the current ISession. Roll back the active ITransaction, dispose the session, and start a new session for any retry.
If the failure points to driver incompatibility, revert the configuration change: set adonet.batch_size to 0 or remove the key, rebuild, and restart. This is the rollback step for a client-side configuration change that alters runtime behavior.
Limitations
- Batching applies only to INSERT, UPDATE, and DELETE statements inside a single
ISessionflush. SELECT statements are not batched. - Operations in separate
ISessioninstances are not combined into one batch. - Batching does not provide atomicity across the batch. Wrap write work in an explicit
ITransactionto define consistency boundaries. - Identity-column insert strategies may require separate key-retrieval round-trips, reducing the benefit for newly inserted entities.
- Very large batch sizes can increase memory pressure and extend database lock duration. Start small and measure throughput.
- Support depends on the underlying ADO.NET provider and NHibernate version. Some drivers may ignore the setting or throw
NotSupportedException.
Practical check
Persist a known number of entities in one transaction, then compare the profiler trace before and after enabling batching. A successful configuration shows fewer database commands for the same write workload, with no batch-related exceptions. If you cannot observe fewer commands, treat the setting as inactive and leave batching disabled until you can test with a supported driver or NHibernate version.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.