NHibernate - Google Project Hosting

advertisement
Sean Chambers






Senior Developer at Flagler County Schools
for 5 years
Owner Hybrid Software, Educational Software
Contributor to various open source projects
(Castle Project, Nhibernate, NUnit, NBehave)
Practicing TDD,DDD,BDD for 2 years
Blog: http://schambers.lostechies.com
Twitter: schambers



ORM stands for Object Relational Mapper
Maps your POCO (plain old clr objects) to
your relational model using XML config
Relieves developer from 95% of common
CRUD code








MSSQL 2000, 2005 etc..
SqlCe, Sqlite, Firebird embedded db’s
MySQL
PostgreSql
Oracle
SyBase
Db2
Many many more
Domain Model
Persistence Layer
NHibernate
Session
SessionFactory
Database
Configuration
SessionFactory
Session
1. SessionFactory consumes the configuration
2. Shared among all application threads
3. Instantiation is expensive as parsing of mapping files is performed
4. Validates mapping files, showing errors if incorrect mapping
5. SessionFactory provides Session objects that are used to interact
with the database
6. A Session object holds an open connection to the database for
loading objects, and transaction management




1. Web.config/app.config
2. Mapping files
Configuration defines db dialect, db connection and mapping
files assembly
Sample mapping file:
<class name=“Order” table=“Orders”>
<id name="Id" type=”int" column=“OrderId" unsaved-value="0">
<generator class=”native"/>
</id>
<property name=“Total” />
<many-to-one name=“Customer” />
</class>

Manages interaction with database, contains all basic CRUD
operations
◦ session.Get(typeof(Order), orderId);
◦ Session.Load(typeof(Order), orderId); will throw exception
◦ session.Save(myOrder);
◦ session.SaveOrUpate(myOrder);
◦ Session.Delete(myOrder);



Query/HQL API
Criteria API
Native SQL


Nhibernate contains an extremely powerful
querying API
IQuery
◦ Provides a method for building a DB query through
HQL (hibernate query language)
IQuery q = session.CreateQuery(“from Orders where Total>:total”)
.SetDecimal(“Total”, 30m)
.OrderBy(Order.Asc(“Title”))
.SetFirstResult(20)
.SetMaxResults(10);
IList<Order> orders = q.List<Order>();

Constructs a query using an API

Is more extensible than HQL
ICritiera crit = session.CreateCriteria(typeof(Order))
.Add(Expression.Gt(“Total”, 30m))
.SetFirstResults(20);
IList<Order> orders = crit.List<Order>();


Allows you to execute native SQL queries
Good for legacy adoption
IList<Order> orders = session.CreateSqlQuery(“select {order.*}
from Order {order} where {order.Total} < 30.00”),
“order”, typeof(Order))
.List<Order>();


NHibernate will track changes performed to
an object a.k.a. “Dirty” objects
Will implicitly call Save:
Order order = session.Load(typeof(Order), orderId);
order.Total = 69.95m;
session.Flush();
Flush() is also called when transaction is committed



Collection Mapping
Component Mapping
Inheritance Mapping


One of the more complex aspects of
NHibernate
Different collection types:
◦
◦
◦
◦



bag : collection of values that are not distinct
list : collection of values that have an index
set : distinct set of values
map :hash/dictionary. Keys and value
Bag and List map to IList<T>, bag with caveats (add method)
Set maps to Iesi.Collections.Generics.HashedSet<T>
Map maps to IDictionary<K, V>




Maps an objects associations into a single table
Good for value objects that do not require an identity (DDD)
Customer.Address with Street and City fields would map to:
Table: Street, Columns AddressStreet, AddressCity etc…
<class name=“Customer” table=“Customer”>
<property name=“FirstName” />
<property name=“LastName” />
<component name=“Address”>
<property name=“Street” />
<property name=“City” />
</component>
</class>


Three different strategies for mapping
inheritance hierarchies
Table per class hierarchy (1 table total)
◦ Uses a discriminator to identify the type of the row
◦ Will have null values for certain columns

Table per subclass (1+n tables)
◦ One for the base class, one table for each subclass

Table per concrete class (n tables)
◦ No table for the base class

Fluent NHibernate
◦ http://code.google.com/p/fluent-nhibernate/

This tool was just recently forked from Jeremy
Miller’s StructureMap






Absolutely necessary with any ORM
Inserts proxies at traversal points
Once navigation to assoc./collection is performed,
NHibernate will retrieve data on-the-fly and
replace the proxy object
Can modify behavior to “Eager” load related objects
Can be problematic in certain scenarios, namely
JSON serialization
Saves you from loading an entire object graph
when all you need is a subset of data

Legacy applications
◦ Often, it is difficult to make your model map to your
established db structure, not impossible however


ETL/Data Mining scenarios
Small Domain Models/No Domain Model

Good post on performance benchmarks:
http://www.iamnotmyself.com/2008/07/02/NHibernateTestingThePerforma
nceUrbanLegend.aspx

Performance benchmark results
Test
1st Run
Nth Run
Inline SQL
1312.5ms
~430ms
Parameterized
Query
1296.9ms
~350ms
SPROC
1390.6ms
~320ms
NHibernate
1565.3ms
~560ms
NHibernate
w/Transaction
1406.3ms
~300ms
nth Run
Download