Book Image

NHibernate 4.x Cookbook - Second Edition

By : Gunnar Liljas, Alexander Zaytsev, Jason Dentler
Book Image

NHibernate 4.x Cookbook - Second Edition

By: Gunnar Liljas, Alexander Zaytsev, Jason Dentler

Overview of this book

NHibernate is a mature, flexible, scalable, and feature-complete open source project for data access. Although it sounds like an easy task to build and maintain database applications, it can be challenging to get beyond the basics and develop applications that meet your needs perfectly. NHibernate allows you to use plain SQL and stored procedures less and keep focus on your application logic instead. Learning the best practices for a NHibernate-based application will help you avoid problems and ensure that your project is a success. The book will take you from the absolute basics of NHibernate through to its most advanced features, showing you how to take full advantage of each concept to quickly create amazing database applications. You will learn several techniques for each of the four core NHibernate tasks—configuration, mapping, session and transaction management, and querying—and which techniques fit best with various types of applications. In short, you will be able to build an application using NHibernate by the end of the book. You will also learn how to best implement enterprise application architecture patterns using NHibernate, leading to clean, easy-to-understand code and increased productivity. In addition to new features, you will learn creative ways to extend the NHibernate core, as well as gaining techniques to work with the NHibernate search, shards, spatial, envers, and validation projects.
Table of Contents (17 chapters)
NHibernate 4.x Cookbook Second Edition
Credits
About the Authors
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface
Index

Configuring NHibernate with hibernate.cfg.xml


NHibernate offers several methods for configuration and a number of configuration settings.

In this recipe, we will show you how to configure NHibernate using the hibernate.cfg.xml configuration file, with a minimal number of settings to get your application up and running quickly. The recipe also forms the base for several other recipes in this chapter.

Getting ready

  1. Complete the steps from the Installing NHibernate recipe in this chapter.

  2. Add a console application project to your solution called ConfigByXml.

  3. Set it as the Startup project for your solution.

  4. Install NHibernate to ConfigByXml project using the NuGet Package Manager Console.

  5. In ConfigByXml, add a reference to the Eg.Core project.

How to do it...

  1. Add an XML file named hibernate.cfg.xml with the following contents:

    <?xml version="1.0" encoding="utf-8"?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
      <session-factory>
        <property name="dialect">
          NHibernate.Dialect.MsSql2012Dialect, NHibernate
        </property>
        <property name="connection.connection_string">
          Server=.\SQLEXPRESS; Database=NHCookbook; 
          Trusted_Connection=SSPI
        </property>
        <property name="adonet.batch_size">
          100
        </property>
      </session-factory>
    </hibernate-configuration>
  2. On the Solution Explorer tab, right-click on hibernate.cfg.xml and select Properties.

  3. Change Copy to Output Directory property from Do not copy to Copy if newer.

  4. Open Program.cs and add using NHibernate.Cfg; to the beginning of the file

  5. Add the following code to the Main method:

    var nhConfig = new Configuration().Configure();
    var sessionFactory = nhConfig.BuildSessionFactory();
    Console.WriteLine("NHibernate Configured!");
    Console.ReadKey();
  6. Build and run your application. You will see the text NHibernate Configured!

How it works...

The connection string we've defined points to the NHCookbook database running under the local Microsoft SQL Server.

Next, we define a few properties that tell NHibernate how to behave.

The dialect property specifies a dialect class that NHibernate uses to build SQL syntax specific to a Relational Database Management System (RDBMS). We're using the Microsoft SQL 2012 dialect. Additionally, most dialects set intelligent defaults for other NHibernate properties, such as connection.driver_class.

The connection.connection_string_name property references our connection string by name.

By default, NHibernate will send a single SQL statement and wait for a response from the database. When we set the adonet.batch_size property to 100, NHibernate will group up to 100 SQL INSERT, UPDATE, and DELETE statements in a single ADO.NET command and send the whole batch at once. In effect, the work of 100 round trips to the database is combined in one. Because a roundtrip to the database is, at best, an out-of-process call, and at worst, a trip through the network or even the Internet, this can improve performance significantly. Batching is currently supported when targeting Microsoft SQL Server, Oracle, or MySQL.

We change Copy to Output directory to ensure that our hibernate.cfg.xml file is copied to the build output directory.

There's more...

By default, NHibernate looks for its configuration in the hibernate.cfg.xml file. However, the Configure method has three extra overloads, which can be used to provide configuration data from other sources, such as:

  • From a different file:

    var cfgFile = "cookbook.cfg.xml"; 
    var nhConfig = new Configuration().Configure(cfgFile);
  • From a file embedded into an assembly file:

    var assembly = GetType().Assembly;
    var path = "MyApp.cookbook.cfg.xml"; 
    var nhConfig = new Configuration().Configure(assembly, path);
  • From an XmlReader:

    var doc = GetXmlDocumentWithConfig();
    var reader = new XmlNodeReader (doc);
    var nhConfig = new Configuration().Configure(reader);

NHibernate architecture

There are several key components to an NHibernate application, as shown in this diagram:

On startup, an NHibernate application builds a Configuration object. In this recipe, we build the configuration from settings in the hibernate.cfg.xml file. The Configuration object is responsible for loading mappings, investigating the object model for additional information, building the mapping metadata, and finally building a session factory. Building the session factory is a rather resource intensive operation, and is normally only done once, when the application starts up.

A session represents a Unit of Work in the application. Martin Fowler defines a Unit of Work as something that "maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems". An NHibernate session tracks changes to entities and writes those changes back to the database all at once. In NHibernate, this process of waiting to write to the database is called transactional write-behind. In addition, the session is the entry point to much of the NHibernate API. More information about the Unit of Work pattern is available at http://martinfowler.com/eaaCatalog/unitOfWork.html and in Fowler's book, Patterns of Enterprise Application Architecture. A session factory is responsible for creating sessions.

The session acts as an intermediary between our application and several key NHibernate components. A typical application will not interact with these components directly, but understanding them is critical to understanding NHibernate. Unlike a session factory, building a session is very cheap.

A dialect is used to build correct SQL syntax for a specific RDBMS. For example, in some versions of Microsoft SQL Server, we begin a select statement with SELECT TOP 20 to specify a maximum result set size. Only 20 rows will be returned. Similarly, to perform this operation in SQLite, we append LIMIT 20 to the end of the select statement. Each dialect provides the necessary SQL syntax string fragments and other information to build correct SQL strings for the chosen RDBMS.

A driver is responsible for building a Batcher, creating IDbConnection and IDbCommand objects, and preparing those commands.

A connection provider is simply responsible for opening and closing database connections.

A batcher manages the batch of commands to be sent to the database and the resulting data readers. Currently, only the SqlClientDriver, OracleDataDriver, and MySqlDataDriver support batching. The drivers that don't support batching provide a NonBatchingBatcher to manage IDbCommands and IDataReaders and simulate the existence of a single logical batch of commands.

NHibernate properties

Here are some of the commonly used NHibernate properties:

Property name

Description

connection.provider

This property is a provider class to open and close database connections.

connection.driver_class

This property is specific to the RDBMS used, and is typically set by the dialect.

connection.connection_string

This property is a database connection string.

connection.connection_string_name

This property is the name of connection string in <connectionStrings> element.

connection.isolation

This property is at the transaction isolation level.

dialect

This property is required. A class to build RDBMS-specific SQL strings. Typically, this is one of the many dialects from the NHibernate.Dialect namespace.

show_sql

This is property is a Boolean value. It is set to true to log all SQL statements to Console.Out. Alternatively, log4net may be used to log to other locations.

current_session_context_class

This property is a class to manage contextual sessions. This is covered in depth in Chapter 3, Sessions and Transactions.

query.substitutions

This property is a comma-separated list of translations to perform on query strings. For example, True=1, Yes=1, False=0, No=0.

sql_exception_converter

This property is a class to convert RDBMS-specific ADO.NET Exceptions to custom exceptions.

prepare_sql

This property is a Boolean value. Prepares SQL statements and caches the execution plan for the duration of the database connection.

command_timeout

This property is the number of seconds to wait for a SQL command to complete before timing out.

adonet.batch_size

This property is the number of SQL commands to send at once before waiting for a response from the database.

generate_statistics

This property enables tracking of some statistical information, such as the number of queries executed and entities loaded.

format_sql

This property adds line endings for easier-to-read SQL statements.

Additional information about each of these settings is available in the reference documentation at http://nhibernate.info/doc/nhibernate-reference/index.html.

Dialects and drivers

Many dialects set other NHibernate properties to sensible default values, including, in most cases, the connection.driver_class. NHibernate includes the following dialects in the NHibernate.Dialect namespace and drivers in the NHibernate.Driver namespace:

RDBMS

Dialect(s)

Driver(s)

Microsoft SQL Server

MsSql2012Dialect

MsSql2008Dialect

MsSqlAzure2008Dialect

MsSql2005Dialect

MsSql2000Dialect

MsSql7Dialect

MsSqlCE40Dialect

MsSqlCEDialect

SqlClientDriver

SqlServerCEDriver

Oracle

Oracle12cDialect

Oracle10gDialect

Oracle9iDialect

Oracle8iDialect

OracleLiteDialect

OracleClientDriver

OracleDataClientDriver

OracleLiteDataDriver

OracleManagedDataClientDriver

MySql

MySQL55Dialect

MySQL5Dialect

MySQL55InnoDBDialect

MySQL5InnoDBDialect

MySQLDialect

MySqlDataDriver

DotConnectMySqlDriver

PostgreSQL

PostgreSQLDialect

PostgreSQL81Dialect

PostgreSQL82Dialect

NpgsqlDriver

DB2

DB2Dialect

Db2400Dialect

DB2Driver

DB2400Driver

Informix

InformixDialect

InformixDialect0940

InformixDialect1000

IfxDriver

Sybase

SybaseASA9Dialect

SybaseASE15Dialect

SybaseSQLAnywhere10Dialect

SybaseSQLAnywhere11Dialect

SybaseSQLAnywhere12Dialect

SybaseAsaClientDriver

SybaseAseClientDriver

SybaseSQLAnywhereDotNet4Driver

SybaseSQLAnywhereDriver

Firebird

FirebirdDialect

FirebirdClientDriver

SQLite

SQLiteDialect

SQLite20Driver

Ingres

IngresDialect

Ingres9Dialect

IngresDriver

See also

  • Configuring NHibernate with hibernate.cfg.xml

  • Configuring NHibernate with code

  • Configuring NHibernate with Fluent NHibernate