Because NHibernate is designed to operate in many different environments, there are a large number of configuration parameters. Fortunately, most have sensible default values and NHibernate is distributed with an example App.config file (found in src\NHibernate.Test) that shows the various options. You usually only have to put that file in your project and customize it.
An instance of NHibernate.Cfg.Configuration represents an entire set of mappings of an application's .NET types to a SQL database. The Configuration is used to build an (immutable) ISessionFactory. The mappings are compiled from various XML mapping files.
You may obtain a Configuration instance by instantiating it directly. Heres an example of setting up a datastore from mappings defined in two XML configuration files:
Configuration cfg = new Configuration() .AddFile("Item.hbm.xml") .AddFile("Bid.hbm.xml");
An alternative (sometimes better) way is to let NHibernate load a mapping file from an embedded resource:
Configuration cfg = new Configuration() .AddClass(typeof(NHibernate.Auction.Item)) .AddClass(typeof(NHibernate.Auction.Bid));
Then NHibernate will look for mapping files named NHibernate.Auction.Item.hbm.xml and NHibernate.Auction.Bid.hbm.xml embedded as resources in the assembly that the types are contained in. This approach eliminates any hardcoded filenames.
Another alternative (probably the best) way is to let NHibernate load all of the mapping files contained in an Assembly:
Configuration cfg = new Configuration() .AddAssembly( "NHibernate.Auction" );
Then NHibernate will look through the assembly for any resources that end with .hbm.xml. This approach eliminates any hardcoded filenames and ensures the mapping files in the assembly get added.
If a tool like Visual Studio .NET or NAnt is used to build the assembly, then make sure that the .hbm.xml files are compiled into the assembly as Embedded Resources.
A Configuration also specifies various optional properties:
IDictionary props = new Hashtable(); ... Configuration cfg = new Configuration() .AddClass(typeof(NHibernate.Auction.Item)) .AddClass(typeof(NHibernate.Auction.Bind)) .SetProperties(props);
A Configuration is intended as a configuration-time object, to be discarded once an ISessionFactory is built.
When all mappings have been parsed by the Configuration, the application must obtain a factory for ISession instances. This factory is intended to be shared by all application threads:
ISessionFactory sessions = cfg.BuildSessionFactory();
However, NHibernate does allow your application to instantiate more than one ISessionFactory. This is useful if you are using more than one database.
An ISessionFactory may open an ISession on a user-provided ADO.NET connection. This design choice frees the application to obtain ADO.NET connections wherever it pleases:
IDbConnection conn = myApp.GetOpenConnection(); ISession session = sessions.OpenSession(conn); // do some data access work
The application must be careful not to open two concurrent ISessions on the same ADO.NET connection!
Alternatively, you can have the ISessionFactory open connections for you. The ISessionFactory must be provided with ADO.NET connection properties in one of the following ways:
Pass an instance of IDictionary mapping property names to property values to Configuration.SetProperties().
Add the properties to a configuration section in the application configuration file. The section should be named nhibernate and its handler set to System.Configuration.NameValueSectionHandler.
Include <property> elements in a configuration section in the application configuration file. The section should be named hibernate-configuration and its handler set to NHibernate.Cfg.ConfigurationSectionHandler. The XML namespace of the section should be set to urn:nhibernate-configuration-2.2.
Include <property> elements in hibernate.cfg.xml (discussed later).
If you take this approach, opening an ISession is as simple as:
ISession session = sessions.OpenSession(); // open a new Session // do some data access work, an ADO.NET connection will be used on demand
All NHibernate property names and semantics are defined on the class NHibernate.Cfg.Environment. We will now describe the most important settings for ADO.NET connection configuration.
NHibernate will obtain (and pool) connections using an ADO.NET data provider if you set the following properties:
Table 3.1. NHibernate ADO.NET Properties
Property name | Purpose |
---|---|
hibernate.connection.provider_class |
The type of a custom IConnectionProvider.
eg. full.classname.of.ConnectionProvider if the Provider is built into NHibernate, or full.classname.of.ConnectionProvider, assembly if using an implementation of IConnectionProvider not included in NHibernate. |
hibernate.connection.driver_class |
The type of a custom IDriver, if using DriverConnectionProvider.
full.classname.of.Driver if the Driver is built into NHibernate, or full.classname.of.Driver, assembly if using an implementation of IDriver not included in NHibernate. This is usually not needed, most of the time the hibernate.dialect will take care of setting the IDriver using a sensible default. See the API documentation of the specific dialect for the defaults. |
hibernate.connection.connection_string | Connection string to use to obtain the connection. |
hibernate.connection.connection_string_name | The name of the connection string (defined in <connectionStrings> configuration file element) to use to obtain the connection. |
hibernate.connection.isolation |
Set the ADO.NET transaction isolation level. Check
System.Data.IsolationLevel for meaningful values
and the database's documentation to ensure that level is supported.
eg. Chaos, ReadCommitted, ReadUncommitted, RepeatableRead, Serializable, Unspecified |
hibernate.connection.release_mode |
Specify when NHibernate should release ADO.NET connections.
See Section 10.7, “Connection Release Modes”.
eg. auto (default) | on_close | after_transaction Note that this setting only affects ISessions returned from ISessionFactory.OpenSession. For ISessions obtained through ISessionFactory.GetCurrentSession, the ICurrentSessionContext implementation configured for use controls the connection release mode for those ISessions. See Section 2.3, “Contextual Sessions”. |
hibernate.adonet.batch_size | Specify the batch size to use when batching update statements. Setting this to 0 (the default) disables the functionality. See Section 15.6, “Batch updates”. |
This is an example of how to specify the database connection properties inside a web.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </configSections> <nhibernate> <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /> <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" /> <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" /> <add key="hibernate.connection.connection_string" value="Server=127.0.0.1; Initial Catalog=thedatabase; Integrated Security=SSPI" /> <add key="hibernate.connection.isolation" value="ReadCommitted" /> </nhibernate> <!-- other app specific config follows --> </configuration>
NHibernate relies on the ADO.NET data provider implementation of connection pooling.
You may define your own plugin strategy for obtaining ADO.NET connections by implementing the interface NHibernate.Connection.IConnectionProvider. You may select a custom implementation by setting hibernate.connection.provider_class.
There are a number of other properties that control the behaviour of NHibernate at runtime. All are optional and have reasonable default values.
System-level properties can only be set manually by setting static properties of NHibernate.Cfg.Environment class or be defined in the <nhibernate> section of the application configuration file. These properties cannot be set using Configuration.SetProperties or be defined in the <hibernate-configuration> section of the application configuration file.
Table 3.2. NHibernate Configuration Properties
Property name | Purpose |
---|---|
hibernate.dialect |
The classname of a NHibernate Dialect - enables
certain platform dependent features.
eg. full.classname.of.Dialect, assembly |
hibernate.default_schema |
Qualify unqualified tablenames with the given schema/tablespace
in generated SQL.
eg. SCHEMA_NAME |
hibernate.use_outer_join |
Enables outer join fetching. Deprecated, use max_fetch_depth.
eg. true | false |
hibernate.max_fetch_depth |
Set a maximum "depth" for the outer join fetch tree
for single-ended associations (one-to-one, many-to-one).
A 0 disables default outer join fetching.
eg. recommended values between 0 and 3 |
hibernate.use_reflection_optimizer |
Enables use of a runtime-generated class to set or get properties of an entity
or component instead of using runtime reflection (System-level property).
The use of the reflection optimizer inflicts a certain startup cost on the
application but should lead to better performance in the long run.
You can not set this property in hibernate.cfg.xml
or <hibernate-configuration> section of the application
configuration file.
eg. true | false |
hibernate.bytecode.provider |
Specifies the bytecode provider to use to optimize the use of reflection in NHibernate.
Use null to disable the optimization completely, lcg
to use lightweight code generation (supported on .NET 2.0 only), and
codedom to use CodeDOM-based code generation (supported on .NET 1.1, has problems
with generic types on .NET 2.0).
eg. null | lcg | codedom |
hibernate.cache.provider_class |
The classname of a custom ICacheProvider.
eg. classname.of.CacheProvider, assembly |
hibernate.cache.use_minimal_puts |
Optimize second-level cache operation to minimize writes, at the
cost of more frequent reads (useful for clustered caches).
eg. true | false |
hibernate.cache.use_query_cache |
Enable the query cache, individual queries still have to be set cacheable.
eg. true | false |
hibernate.cache.query_cache_factory |
The classname of a custom IQueryCacheFactory interface,
defaults to the built-in StandardQueryCacheFactory.
eg. classname.of.QueryCacheFactory, assembly |
hibernate.cache.region_prefix |
A prefix to use for second-level cache region names.
eg. prefix |
hibernate.query.substitutions |
Mapping from tokens in NHibernate queries to SQL tokens
(tokens might be function or literal names, for example).
eg. hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC |
hibernate.show_sql |
Write all SQL statements to console.
eg. true | false |
hibernate.hbm2ddl.auto |
Automatically export schema DDL to the database when the
ISessionFactory is created. With
create-drop, the database schema
will be dropped when the ISessionFactory
is closed explicitly.
eg. create | create-drop |
hibernate.use_proxy_validator |
Enables or disables validation of interfaces or classes specified
as proxies. Enabled by default.
eg. true | false |
You should always set the hibernate.dialect property to the correct NHibernate.Dialect.Dialect subclass for your database. This is not strictly essential unless you wish to use native or sequence primary key generation or pessimistic locking (with, eg. ISession.Lock() or IQuery.SetLockMode()). However, if you specify a dialect, NHibernate will use sensible defaults for some of the other properties listed above, saving you the effort of specifying them manually.
Table 3.3. NHibernate SQL Dialects (hibernate.dialect)
RDBMS | Dialect | Remarks |
---|---|---|
DB2 | NHibernate.Dialect.DB2Dialect | |
DB2 for iSeries (OS/400) | NHibernate.Dialect.DB2400Dialect | |
Ingres | NHibernate.Dialect.IngresDialect | |
PostgreSQL | NHibernate.Dialect.PostgreSQLDialect | |
PostgreSQL 8.1 | NHibernate.Dialect.PostgreSQL81Dialect | This dialect supports FOR UPDATE NOWAIT available in PostgreSQL 8.1. |
PostgreSQL 8.2 | NHibernate.Dialect.PostgreSQL82Dialect | This dialect supports IF EXISTS keyword in DROP TABLE and DROP SEQUENCE available in PostgreSQL 8.2. |
MySQL 3 or 4 | NHibernate.Dialect.MySQLDialect | |
MySQL 5 | NHibernate.Dialect.MySQL5Dialect | |
Oracle (any version) | NHibernate.Dialect.OracleDialect | |
Oracle 9/10g | NHibernate.Dialect.Oracle9Dialect | |
Sybase Adaptive Server Enterprise | NHibernate.Dialect.SybaseDialect | |
Sybase Adaptive Server Anywhere | NHibernate.Dialect.SybaseAnywhereDialect | |
Microsoft SQL Server 2000 | NHibernate.Dialect.MsSql2000Dialect | |
Microsoft SQL Server 2005 | NHibernate.Dialect.MsSql2005Dialect | |
Microsoft SQL Server 2005 Everywhere Edition | NHibernate.Dialect.MsSqlCeDialect | |
Microsoft SQL Server 7 | NHibernate.Dialect.MsSql7Dialect | |
Firebird | NHibernate.Dialect.FirebirdDialect | Set hibernate.driver_class to NHibernate.Driver.FirebirdClientDriver for Firebird ADO.NET provider 2.0. |
SQLite | NHibernate.Dialect.SQLiteDialect | Set hibernate.driver_class to NHibernate.Driver.SQLite20Driver for System.Data.SQLite provider for .NET 2.0. |
Ingres 3.0 | NHibernate.Dialect.IngresDialect |
Additional dialects may be available in the NHibernateContrib package (see Part I, “NHibernateContrib Documentation”). At the time of writing this package contains support for Microsoft Access (Jet) database engine.
If your database supports ANSI or Oracle style outer joins, outer join fetching might increase performance by limiting the number of round trips to and from the database (at the cost of possibly more work performed by the database itself). Outer join fetching allows a graph of objects connected by many-to-one, one-to-many or one-to-one associations to be retrieved in a single SQL SELECT.
By default, the fetched graph when loading an objects ends at leaf objects, collections, objects with proxies, or where circularities occur.
For a particular association, fetching may be configured (and the default behaviour overridden) by setting the fetch attribute in the XML mapping.
Outer join fetching may be disabled globally by setting the property hibernate.max_fetch_depth to 0. A setting of 1 or higher enables outer join fetching for one-to-one and many-to-one associations which have been mapped with fetch="join".
See Section 15.1, “Fetching strategies” for more information.
In NHibernate 1.0, outer-join attribute could be used to achieve a similar effect. This attribute is now deprecated in favor of fetch.
You may integrate a process-level (or clustered) second-level cache system by implementing the interface NHibernate.Cache.ICacheProvider. You may select the custom implementation by setting hibernate.cache.provider_class. See the Section 15.2, “The Second Level Cache” for more details.
You may define new NHibernate query tokens using hibernate.query.substitutions. For example:
hibernate.query.substitutions true=1, false=0
would cause the tokens true and false to be translated to integer literals in the generated SQL.
hibernate.query.substitutions toLowercase=LOWER
would allow you to rename the SQL LOWER function.
NHibernate logs various events using Apache log4net.
You may download log4net from http://logging.apache.org/log4net/. To use log4net you will need a log4net configuration section in the application configuration file. An example of the configuration section is distributed with NHibernate in the src/NHibernate.Test project.
We strongly recommend that you familiarize yourself with NHibernate's log messages. A lot of work has been put into making the NHibernate log as detailed as possible, without making it unreadable. It is an essential troubleshooting device. Also don't forget to enable SQL logging as described above (hibernate.show_sql), it is your first step when looking for performance problems.
The interface NHibernate.Cfg.INamingStrategy allows you to specify a "naming standard" for database objects and schema elements.
You may provide rules for automatically generating database identifiers from .NET identifiers or for processing "logical" column and table names given in the mapping file into "physical" table and column names. This feature helps reduce the verbosity of the mapping document, eliminating repetitive noise (TBL_ prefixes, for example). The default strategy used by NHibernate is quite minimal.
You may specify a different strategy by calling Configuration.SetNamingStrategy() before adding mappings:
ISessionFactory sf = new Configuration() .SetNamingStrategy(ImprovedNamingStrategy.Instance) .AddFile("Item.hbm.xml") .AddFile("Bid.hbm.xml") .BuildSessionFactory();
NHibernate.Cfg.ImprovedNamingStrategy is a built-in strategy that might be a useful starting point for some applications.
An alternative approach is to specify a full configuration in a file named hibernate.cfg.xml. This file can be used as a replacement for the <nhibernate;> or <hibernate-configuration> sections of the application configuration file.
The XML configuration file is by default expected to be in your application directory. Here is an example:
<?xml version='1.0' encoding='utf-8'?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <!-- an ISessionFactory instance --> <session-factory> <!-- properties --> <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property> <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> <property name="connection.connection_string">Server=localhost;initial catalog=nhibernate;User Id=;Password=</property> <property name="show_sql">false</property> <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property> <property name="use_outer_join">true</property> <!-- mapping files --> <mapping resource="NHibernate.Auction.Item.hbm.xml" assembly="NHibernate.Auction" /> <mapping resource="NHibernate.Auction.Bid.hbm.xml" assembly="NHibernate.Auction" /> </session-factory> </hibernate-configuration>
Configuring NHibernate is then as simple as
ISessionFactory sf = new Configuration().Configure().BuildSessionFactory();
You can pick a different XML configuration file using
ISessionFactory sf = new Configuration() .Configure("/path/to/config.cfg.xml") .BuildSessionFactory();