NHibernate

Links:

    • NHibernate home page (NHForge) - link. Download link.
    • NHContrib (link) - includes
      • 2nd level cache providers support
      • validation
    • Getting Started Guide - link.
  • Wiki

Helpers:

Older material:

    • Linq to NHibernate (link). The Linq support is now built in (with version 3).
    • HQL AddIn for Visual Studio (link).
    • NHibernate Query Generator (link)
    • Spring Framework (link)

Instructions:

Batch processing (link)

NHibernate - Learning with Code Samples (link).

Your first NHibernate application (link).

For lazy loading, check the following blog post.

Working in disconnected scenarios (like web applications) - link.

Using ICriteria and Paged Queries in DAL, by PacktPub (link).

Linq for NHibernate - QueryOver (link).

Repository example (link).

Mapping the same class to a view and a table using entity-name (link).

Hibernate Query Language (HQL) - (link)

Improving performance (link).

How to map a tree in NHibernate (link) - Loading a complex object graph (link)

Best Practices (link). See S#arp Architecture section below.

Composite Keys

Using composite keys: video (link), blog post (link). When using composite keys you have to implement/override Equals and GetHashCode functions (link).

NHibernate and Composite Keys article (link).

Fluent NHibernate

Database configuration (link).

QuickStart - Setting up NHibernate with Fluent interface

Download NHibernate binaries. Download Fluent source from GitHub. Fluent libraries currently have to be recompiled against v3.0.0 Beta 1 of NHibernate. Copy newer NHibernate binaries to the Tools directory of Fluent source and recompile.

Add the following references to your project: NHibernate, Fluent, NHibernate.ByteCode.Castle (or other for lazy-loading).

Add NHibernateHelper (see attached) and Repository classes. Implement Repository pattern from the Repository Example above. The classes there use Fluent for NHibernate configuration.

Set up your connection string and override for Repository class that accepts showSQL parameter.

Add your domain classes, Map classes, and create Repository classes (if needed).

Create Domain directory that will contain domain entities. Create Mappings subdirectory to contain Fluent mapping classes.

Caching

NHibernate supports two levels of cache.

Second level cache is using an external provider for data storage. Download the cache provider libraries from the link below. SysCache (IIS caching) is a common one, for example. Then do the following items (note that I use Fluent for configuration):

    • NHibernateHelper, in CreateSessionFactory, add
      • sqlConfiguration.Cache(c => c
      • .UseQueryCache()
      • .UseMinimalPuts()
      • .ProviderClass<NHibernate.Caches.SysCache.SysCacheProvider>()
      • );
    • In mapping file (ClassMap), set
    • Cache.ReadWrite();or any desired value.
    • In your code, use or
      • var q = Session.CreateQuery("from Department")
      • .SetCacheable(true); or to
        • Session.QueryOver<Department>().Cacheable();
    • To cache objects you modify, make sure you use Transaction object and commit changes in transaction.commit(), otherwise they do not propagate to the 2nd level cache. See "Fluent NHibernate and 2nd level cache" article at the link below.

For more details read the articles below.

    • Quickly setting up and using 2nd level cache (link).
    • Fluent NHibernate and 2nd level cache (link).
    • Using SysCache as ... (link)

Downloads:

    • NHibernate Cache Providers (link).

Retrieving Related Entities from Three Tables

In a scenario with three tables left joined (Department -> Category -> Reason) this is the way to get the tree, using ICriteria:

[Test]

public void icCleanResults_ThisIsIt()

{

var cr = Session.CreateCriteria<Domain.Department>()

.SetFetchMode("Categories", FetchMode.Eager)

.SetFetchMode("Categories.Reasons", FetchMode.Eager);

var result = cr.SetResultTransformer(new DistinctRootEntityResultTransformer())

.List();

DisplayContents(result);

}

This code will retrieve all the data in just one database query and remove duplicate entities on the client side so that operating on the results will be as expected (no duplicate rows as a result of left join query). DisplayContents simply iterates through the Department list and displays the children in a hierarchical tree using simple foreach nested loop.

And now the same thing, using QueryOver:

[Test]

public void linqCriteria()

{

var l = Session.QueryOver<Domain.Department>()

.Fetch(d => d.Categories).Eager

.Fetch(c => c.Categories[0].Reasons).Eager;

var result = l.TransformUsing(new DistinctRootEntityResultTransformer()).List();

DisplayContents(result);

}

However, this *IS* duplicating rows for non-root elements (Categories in this case).

Finally, here is the proper result:

[Test]

public void linq4()

{

var result = Session.QueryOver<Domain.Department>()

.Left.JoinQueryOver<Domain.Category>(d => d.Categories)

.Left.JoinQueryOver<Domain.Reason>(c => c.Reasons)

.TransformUsing(Transformers.DistinctRootEntity)

.List();

DisplayContents(result);

}

In addition to this code, the child collections have to be Sets, not Bags. In the Department, declare Categories collection as

public virtual ICollection<Category> Categories { get; protected set; }

and implement it as

this.Categories = new HashSet<Category>();

Then, in the mapping file, use

HasMany<Category>(m => m.Categories)

.KeyColumn("DepartmentId")

.Inverse()

.Cascade.All()

.AsSet();

WCF with NHibernate

See also the section about WCF under S#arp Architecture (below).

Fabio Maulo's post (link).

IglooCoder's WcfNHibernate (link)