Posts Tagged ‘NHibernate’
KeyNotFoundException from NHibernate’s Session.Evict
We started getting KeyNotFoundException when we evict an entity from session. The error is not consistent, some time it work and some time it wont. Searched a lot for the cause of this exception but not got any proper solution.
As per the stack trace, the error is because it couldn’t find the key in a collection. In a collection an entities identity is based on the hash code. In this case the entity has composite key. In the GetHashCode function, we append the values of composite properties and get the hash code of the resultant string. When I start checking in more details I saw some properties we used in getting hash code is not exist as part composite key in the mapping file (some keys were removed from the composite mapping but not updated GetHasCode()). I need to do some more analysis to find why those extra fields screwing up the GetHashCode function. I will update the post later if I get the answer.
To avoid these kind of issues make sure to use only composite properties in the Equal and GetHashCode function and avoid using properties that are not part of composite.
Happy coding…
Persist Domain Model using NHibernate
Last couple of days I was spending time with NHibernate. I went through several articles and books related to NHibernate. I learned bits and pieces about hibernate, next step for me is to implement what ever I learned so far. I choose a small Sales Tax problem for learning NH.
Object Relational Mappers are best suited in Object oriented development (OOD). In OOD process the designer first implement the domain model based on the business requirement. Then use any ORM to persist. In this approach we are giving importance to domain model then comes the db modelling. Domain model and NHibernate will go hand in hand. A designer can design the domain model without thinking much about persistence. Anyway I am not going much in detail of Domain models, you all can read more from Patterns of Enterprise Application Architecture and Domain-Driven Design: Tackling Complexity in the Heart of Software
Below is the rough diagram of domain model I created
Let’s go through Order Entity
namespace DDD.DomainModel { public class Order { private IList<OrderLine> _lineItems; private Customer _customer; private ISalesTaxCalculator _salesCalculator; private int _orderId; private Order() { } public Order(Customer customer, ISalesTaxCalculator salesCalculator) { this._customer = customer; this._lineItems = new List<OrderLine>(); this._salesCalculator = salesCalculator; } public int OrderId { get { return _orderId; } } public Order With(OrderLine orderLine) { Money tax = _salesCalculator.CalculateTax(orderLine); orderLine.SetTaxAmount(tax); orderLine.SetOrder(this); _lineItems.Add(orderLine); return this; } public Money GetTotalTax() { Money totalTax = Money.Empty(); for (int i = 0; i < _lineItems.Count; i++) totalTax += _lineItems[i].GetTaxAmount(); return totalTax; } public Money GetGrandTotal() { Money total = Money.Empty(); for (int i = 0; i < _lineItems.Count; i++) total += _lineItems[i].GetSubTotal(); return total; } public int GetNumberOfItems() { return this._lineItems.Count(); } public virtual IList<OrderLine> LineItems { get { return _lineItems; } } public Customer Customer { get { return _customer; } } } }
As you could see in the order class there is no Getter/Setter properties for setting the data from db. One of the good feature of NHibernate is, it can set or get data from private fields via reflection. It helps us to maintain Immutability in entities.
Mapping File
Hibernate uses xml configuration files to map Entities to database tables. Let’s see the configuration file for Order entity.
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping default-access="field" xmlns="urn:nhibernate-mapping-2.2" auto-import="true"> <class name="DDD.DomainModel.Order,DDD.DomainModel" lazy="false" table="[Order]"> <id name="OrderId" column="order_id" access="nosetter.camelcase-underscore"> <generator class="native"></generator> </id> <bag name="LineItems" cascade="all-delete-orphan" access="nosetter.camelcase-underscore" lazy="true"> <key column ="order_id"/> <one-to-many class ="DDD.DomainModel.OrderLine,DDD.DomainModel"/> </bag> <many-to-one name="Customer" column="customer_id" not-null="false" cascade="none"
access="nosetter.camelcase-underscore" update="false"
class="DDD.DomainModel.Customer,DDD.DomainModel"/> </class> </hibernate-mapping>
Let’s go through the config file
In the class tag, I mapped the Order class with the database table Order. Inside the class tag provide the mappings for the fields to the table row.
id tag tells hibernate that the field is an Identity field, here I mapped _orderId to column order_id. So what is this access property. It will directs the hibernate from where to get/set the value. Here I set as nosetter.camelcase-underscore. I explain that part later.
Bag tag tells hibernate that LineItems is a collection. Inside bag we define the relationship with orderline.
Access Attribute
Hibernate can set value to private fields or to property. Hibernate uses ‘access’ attribute to determine this.
field: Set access to field (access=’field’) directs hibernate to read values from private field during persisting and while fetching it sets the private field with the value from database. I feel it’s a very important feature, this makes objects hides the data and exposed through predefined interfaces.
property: Set access to property (access=’property’) directs hibernate to get and set values to the properties.
nosetter.*: Set access to property (access=’nosetter’) directs hibernate to get values from property of the field mentioned but set value to private field. Let’s explain with an e.g.
private Customer _customer;
public Customer Customer { get { return _customer; } }
In xml we configure like
<many-to-one name="Customer" column="customer_id" not-null="false" cascade="none" access="nosetter.camelcase-underscore" …./>
This tells hibernate while persisting get the value from the Customer property but while setting the value from db uses the variable field (with same name as property) in camelcase-underscore format, here it will set the value to _customer.
You all can see the rest of the configuration in the source code.
Hibernate Repository
I created a generic repository for Hibernate just like the one I created for Entity Framework. Let’s go through the hibernate repository.
public class HibernateRepo:IRepository { IList _itemsAdded = new System.Collections.ArrayList(); ISession _session; private static ISessionFactory CreateSessionFactory() { Configuration cfg = new Configuration().Configure(); return cfg.BuildSessionFactory(); } private ISession Session { get { if (_session!=null && _session.Connection.State != System.Data.ConnectionState.Open) { _session.Connection.Close(); _session.Connection.Open(); } if (_session == null || _session.IsOpen == false) _session = CreateSessionFactory().OpenSession(); return _session; } } ITransaction _currentTransaction = null; public void BeginTransaction() { _currentTransaction= this.Session.BeginTransaction(); } public void CommitTransaction() { if (_currentTransaction != null) _currentTransaction.Commit(); } public void Rollback() { if(_currentTransaction!=null) _currentTransaction.Rollback(); } public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class { return this.Session.Query<TEntity>(); } public IList<TEntity> GetAll<TEntity>() where TEntity : class { return this.GetQuery<TEntity>().AsEnumerable<TEntity>().ToList(); } public IList<TEntity> Find<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class { IList<TEntity> entities= this.GetQuery<TEntity>().Where(criteria).ToList(); NHibernateUtil.Initialize(entities); return entities; } public TEntity Single<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class { TEntity entity= this.GetQuery<TEntity>().SingleOrDefault<TEntity>(criteria); return entity; } public TEntity First<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> criteria) where TEntity : class { TEntity entity = this.GetQuery<TEntity>().FirstOrDefault<TEntity>(criteria); return entity; } public void Add<TEntity>(TEntity entity) where TEntity : class { _itemsAdded.Add(entity); } public void Delete<TEntity>(TEntity entity) where TEntity : class { this.Session.Delete(entity); } public void Delete<TEntity>(IEnumerable<TEntity> entites) where TEntity : class { throw new NotImplementedException(); } public void SaveChanges() { for (int i = 0; i < _itemsAdded.Count; i++) { this.Session.SaveOrUpdate(_itemsAdded[i]); } } public void Dispose() { if (this.Session != null) { _session.Close(); _session.Dispose(); } if (this._currentTransaction != null) _currentTransaction.Dispose(); } }
Most of the functions are same as the one I created for EF. Let’s go through some function I added for hibernate.
You might wonder why there is no connection string mentioned in this class, also there is no reference about the mapping xml files. How hibernate get all these information? Hibernate uses a configuration file called ‘hibernate.cfg.xml’. This file should exist in the bin folder. This file is not mandatory, you can directly give all the information to hibernation while creating session. Let’s see the configuration file
<?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory> <property name="connection.provider"> NHibernate.Connection.DriverConnectionProvider </property> <property name="connection.driver_class"> NHibernate.Driver.SqlClientDriver </property> <property name="connection.connection_string"> Data Source=PROLAPE00700\SQLSERVER;Initial Catalog=SASales;
Persist Security Info=True;User ID=sony;pwd=sony </property> <property name="proxyfactory.factory_class">
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
</property> <property name="dialect"> NHibernate.Dialect.MsSql2008Dialect </property> <mapping assembly="DDD.Infrastructure.Persistance"/> </session-factory> </hibernate-configuration>
I configured connection string and mapping assembly here. Hibernate uses mapping assembly tag to find out here the mapping files located and it fetches from the assembly using reflection. One thing to remember is the mapping files Build Action should be Embedded Resource.
How this configuration file get passed to hibernate? Have a look at the static function in the repository called CreateSesstionFactory().
private static ISessionFactory CreateSessionFactory() { Configuration cfg = new Configuration().Configure(); return cfg.BuildSessionFactory(); }
When we call Configuration().Configure() hibernate search for the above configuration file and uses the settings in the file to configure the session.
Once you go through the source you might understand how easy we can persist out domain models with less effort.
Download Source Code
Entity Framework Vs NHibernate
I worked on EF POCO model for some times and I come across with several stopovers. EF doesn’t have a very good error reporting, it will just throw some error and we need to run pillar to post to find out why on earth we are getting this error. Another issue is working in disconnected mode, I will explain in detail later in this post. For testing I used EF CTP5, hopefully things might have improved in the latest release.
After dating with EF for quiet some time, I realized that EF is not matured enough to hang around with, it’s still evolving and need time. I thought I need to look around and see any other beautiful and healthy ORM’s around. Yes I do aware of NHibernate a powerful ORM in the market for quiet a long period. So I decided to see in depth. I decided to write a small app to compare both ORM’s. For my comparison I used FluentNHibernate, I like to map my entities to table using code rather than an xml.
I haven’t completed the comparison yet. One of the important focus of my test is how CRUD operation works in disconnected model. In connected model the context can keep track of the changes and do the necessary Create/Update/Delete operation without much issue. So my test app have a WCF service to supply data to presentation layer.
First Test
The presentation layer issue a search request and get an author object from the WCF service, make some changes to author data and send it back to service for persisting it.
Entity Framework: Presentation layer get author object, did some changes to First Name. Sent the modified object to Service for persisting. In the persistence layer attached the author object to ObjectContext and called SaveChanges(). But nothing happened, EF couldn’t recognize the changes made to the object and didn’t persist the changes.
NHibernate: Presentation layer get author object, did some changes to First Name. Sent the modified object to Service for persisting. In the persistence layer make a call to SaveOrUpdate() of Session object with the modified entity. I could see that the changes get persisted to the db.
Test Summary
In my first test I could see that update operation in disconnected mode is pretty easy in NHibernate than EF. I am not sure whether am doing some thing wrong in EF thus it’s not persisting. But from a devs stand point we really don’t want to do much stuffs with an ORM to persist any changes. It’s ORM’s headache to figure out whether the entity state is dirty or not, if dirty then update it.
After this small test I feel like I need to embrace NHibernate as my ORM. Also one of the good feature of NHibernate is it’s error reporting. NH will report error with sql statement it issued to db, it will be helpful for a dev to analyze the error and take necessary actions.
EF might be strong in Autogenerated code, with EDMX, blah, blah. But not yet matured enough to support POCO model. In my point of view NHibernate is the right ORM to choose in comparison with Entity Framework, if you are serious in POCO model.
Note: NHibernate uses lazy loading extensively and you may have some trouble in WCF side while serializing it. It’s advisable to use DTO to transfer data between layers. Trent Foley have a nice post to explain how to perform eager loading with NHibernate.
This is just an initial test and I will move forward to test different scenarios. If I get time I will post the results in future posts.
Overview of Test Application
The test application consist of Presention layer (Winform), WCF service, Domain model and Persistence layer. The service layer and the persistence layer is loosely coupled. At any point of time Service layer doesn’t know to whom he is interacting, it can be EF repository instance or NH instance, I achieved it by Caste Windsor IOC. This loosely coupled approach help me to compare both ORM without any single code change rather with a xml configuration change.
For the test app I used Pubs database. One of domain entity is shown below.
namespace ORM.Domain { [DataContract] public class Author { [DataMember] public virtual string Id { get; private set; } [DataMember] public virtual string LastName { get; set; } [DataMember] public virtual string FirstName { get; set; } [DataMember] public virtual string Phone { get; set; } [DataMember] public virtual string Address { get; set; } [DataMember] public virtual IList<Titles> TitlesAuthored { get; set; } public virtual bool Contract { get; set; } public Author() { this.TitlesAuthored = new List<Titles>(); } public virtual void AddTitles(Titles titles) { this.TitlesAuthored.Add(titles); titles.Authors.Add(this); } }
It’s just a anemic entity without much responsibility. Anyway my focus is not in DDD, so just bare with my entity structure.
Now I need to map my entity to Author table. I used fluent API’s of the ORM to do the mapping.
Entity Framework Mapping
public class AuthorConfiguration:EntityTypeConfiguration<Author> { public AuthorConfiguration() { HasKey(a => a.Id); HasMany(a => a.TitlesAuthored); Property(a => a.Id).HasColumnName("au_id"); Property(a => a.Address).HasColumnName("address"); Property(a => a.FirstName).HasColumnName("au_fname"); Property(a => a.LastName).HasColumnName("au_lname"); Property(a => a.Phone).HasColumnName("phone"); Property(a => a.Contract).HasColumnName("contract"); ToTable("dbo.authors"); } }
FluentHibernate Mapping
public class AuthorMap:ClassMap<Author> { public AuthorMap() { Id(x => x.Id,"au_id"); Map(x => x.LastName, "au_lname"); Map(x => x.FirstName, "au_fname"); Map(x => x.Address, "address"); Map(x => x.Phone, "phone"); Map(x => x.Contract, "contract"); HasManyToMany(t => t.TitlesAuthored).Cascade.All().Table("titleauthor")
.ChildKeyColumn("title_id")
.ParentKeyColumn("au_id");Table("dbo.authors"); } }
What ever I posted here is just my findings. Don’t consider this as a benchmark. You better consider your scenarios and do a small tracer and find out which suites your requirement. Pay careful attention before deciding on any ORM else you will suffer later.
I think it’s better to stop here, you all can look into my source code for more details. I uploaded my test application to Sky drive, if interested pls have a look at it.