NHibernate
Links:
- NHibernate home page (NHForge) - link. Download link.
- NHContrib (link) - includes
- 2nd level cache providers support
- validation
- Getting Started Guide - link.
- Wiki
Helpers:
- A Fluent interface for NHibernate (link to post).
- Getting Started guide (link)
- Source repository at http://github.com/jagregory/fluent-nhibernate
- Sharp Architecture
- Wiki (link)
- Source repository https://github.com/codai/Sharp-Architecture
- NHibernate Query Analyzer (link)
- NHibernate Mapping Generator (link)
Older material:
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.
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)