Sean Chambers
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
Database NHibernate SessionSessionFactory Persistence Layer Domain Model
Configuration SessionFactorySession 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:
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 orders = q.List (); IQuery q = session.CreateQuery(“from Orders where Total>:total”).SetDecimal(“Total”, 30m).OrderBy(Order.Asc(“Title”)).SetFirstResult(20).SetMaxResults(10); IList orders = q.List ();
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 orders = crit.List (); ICritiera crit = session.CreateCriteria(typeof(Order)).Add(Expression.Gt(“Total”, 30m)).SetFirstResults(20); IList orders = crit.List ();
Allows you to execute native SQL queries Good for legacy adoption IList orders = session.CreateSqlQuery(“select {order.*} from Order {order} where {order.Total} ();
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(); 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, bag with caveats (add method) Set maps to Iesi.Collections.Generics.HashedSet Map maps to IDictionary
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…
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 ◦ 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: nceUrbanLegend.aspx nceUrbanLegend.aspx Performance benchmark results Test nth Run 1 st RunNth Run Inline SQL1312.5ms~430ms Parameterized Query ms~350ms SPROC1390.6ms~320ms NHibernate1565.3ms~560ms NHibernate w/Transaction ms~300ms