To a NHibernate 2.0

NHibernate has the 1.2.0 GA version, also it’s preparing to the 2.0 version that will have many ports from Hibernate 3.2.5 GA for Java.

At this time many changes were made to the NHibernate Core, big re-structurations to get into the new features.

Some features of 2.0 version:

StatelessSession: IStatelessSession it’s the interface that allow us to use sessions without first-level cache. Specially created for do bulks Saves/Updates/Deletes. IStateless has a similar semantic to ISession. Now, ISessionFactory it’s responsible of the factory of ISession as well too, IStatelessSession.

EventListeners: that feature allow us to intercept actions that NHibernate has taken before or after to achieve it. With the current version of NHibernate we only can make interceptions using the interfaces ILifecycle and IInterceptors. Now we can "talk" with NHibernate at a low level, before the Save has achieved it, or after as well.

EntityName: that feature allow us to use the classes with a unique name. We could use 1 class with 2 differents entity names (impossible so far). Something that will disapear at NHibernate are the types specifications in queries like typeof(<Type’s name>), only the Entity Name and Generics methods will stay. For example:

  • Session.Get<Foo>(id);
  • Session.Get("TheFooEntity",id);

Both are equivalents queries, the 2nd it’s a method that returns a System.Object and using the Entity Name feature. A preview of this you can see at trunk in IStatelessSession, that has the methods structured at this maner. As you can see, this will cause a breaking change at ISession structure.

DetachedQuery: this the DetachedCriteria’s brother but to HQL, this feature allow us to create queries detached of a Session, that help to play at our DAO implementation. It was a miss feature at NHibernate, to many things you can not do with Criteria. This implementation was available to many times ago at uNHAddIns, you can see here and here.

Stadistics: with this feature we will can do stadistics of our queries primarily. An example of this, that I’m shure you gonna love it, it’s maner that you can calculate the hit-ratio cache.

All between Transactions: it’s another breaking change to get the same behavior that Hibernate. When we will do a CRUD operation, we must put it between transactions. At the current version is not need it.

Why use named queries with NHibernate

At chat with Fabio Maulo, he tell me about the goodness of use Named Queries with NHibernate and that it’s the reason for this post.

What is Named Query ? It’s a Query that are defined at mapping files and have a unique name, could be
in HQL or Native SQL.

A HQL named query could be written like this:

  <query name="Foo-by-name" cacheable="false" read-only="true">
    <![CDATA[        
        from Foo where Name like :value        
    ]]>    
  </query>

And the equivalent named query for Native SQL could be written in this way:

  <sql-query name="Foo-by-name" cacheable="false" read-only="true">
    <return alias="foo" class="Foo"/>
    <![CDATA[ 
    SELECT 
    {foo}.ID AS {foo.Id},    
    {foo}.NAME AS {foo.Name},
    {foo}.MISC AS {foo.Misc}        
    FROM Foo {foo} 
    WHERE {foo}.Name LIKE :value
    ]]>
  </sql-query>

The code that execute the query:

    Foo f1 = new Foo();                    
    f1.Misc = "misc 1";
    f1.Name = "foo 1";        
    session.Save(f1);

    Foo f2 = new Foo();
    f2.Misc = "misc 2";
    f2.Name = "foo 2";
    session.Save(f2);

    session.Flush();

    IQuery q = session.GetNamedQuery("Foo-by-name");
    q.SetString("value", "f%");

    Debug.Assert(q.List().Count == 2);

As you see, both named queries are executed with the same code ;)

Advantages:

  • If we change the RDBMS, we must change the native query at mapping instead of code.
  • If we have HQL queries and we want use a special RDBMS feature, we only must write the equivalent query at Native SQL and do not touch the code.
  • Very Important! And practicly… the reason for this post. The named queries are parsed once when you call to .BuildSessionFactory() and used forever! So that if we write a wrong query (i.e. mistake on a property name), NHibernate make the advice throwing an exception. The queries that you write at code (non-Named Queries) are parsed all the time unless cached. NHibernate now provide a MRU cache for the non-Named Queries of 128 positions, to parse queries the least amount of times.
  • Clean code !
  • Avoid build handcraft queries, making use and abuse of String.Format(…), and wasting positions at the MRU cache of course.

 

Thanks Fabio for the info !

StatelessSession: NHibernate without first-level cache

In the next NHibernate release will be available this feature ported by Fabio Maulo (key developer at NHibernate project), now it’s partial ready to test at trunk. What it does? In orden to get a NHibernate session without the first level cache we must use IStateless session interface (similar syntax to ISession). We must to remember using ISession that cache it’s mandatory, and until now it was imposible to work without it at NHibernate. For what? Was specially maded for bulk operations against the database. Check it out this code:

        using (ISessionFactory sf = cfg.BuildSessionFactory())
            {
                using (IStatelessSession session = sf.OpenStatelessSession())
                {
                    using (ITransaction tx = session.BeginTransaction())
                    {
                        Foo f = new Foo();

                        f.Id = 1;
                        f.Misc = "m1";
                        f.Name = "n1";

                        session.Insert(f);

                        f.Id = 2;

                        session.Insert(f);

                        tx.Commit();

                        Debug.Assert(session.CreateQuery("from Foo")
                                                    .List().Count == 2);
                    }
                }
            }

As you se, the f object was created once and sent to persist twice with the property Id changed, first with ’1′ and then with ’2′. And the result was 2 objects saved. In a common scenario with the first level cache this doesn’t work, because NHibernate “remember” the object f since was saved at first time and a error would be thrown. Notice to save the object we use Insert(…) instead Save(…). The sintax between IStalessSession and ISession are similar, not equals. To make work this example with first-level cache it’s mandatory that NHiberante “forget” the object that was saved. In order to get it, we need make Evict(…) – as you can image, this method are not included at IStatelessSession, even the Flush(…) method. The example look like this:

            using (ISessionFactory sf = cfg.BuildSessionFactory())
            {
                using (ISession session = sf.OpenSession())
                {
                    using (ITransaction tx = session.BeginTransaction())
                    {
                        Foo f1 = new Foo();

                        f1.Id = 1;
                        f1.Misc = "m1";
                        f1.Name = "n1";

                        session.Save(f1);

                        //Remove the object from cache
                        session.Evict(f1); 

                        f1.Id = 2;

                        session.Save(f1);

                        tx.Commit();

                        Debug.Assert(session.
                             CreateQuery("from Foo").List().Count == 2);

                    }
                }
            }

Resources:

NHibernate Stadistics – Go Fabio Go

Fabio Maulo, important developer at NHibernate team, always was contributed with patchs to NHibernate, now it’s porting many features from Hibernate 3.2.5. GA -you can see here and here. Now go for Hibernate Statistics

This it’s the best part of the post, when calculate the cache hit-ratio:

double queryCacheHitCount  = stats.getQueryCacheHitCount();
double queryCacheMissCount = stats.getQueryCacheMissCount();
double queryCacheHitRatio = queryCacheHitCount / (queryCacheHitCount + queryCacheMissCount);

Cool uh?

NHibernate EventListeners

In this postwe talking about StatelessSession the new feature of NHibernate 2.0.0, so another feature available at trunk (port of Hibernate too) are the EventListeners. With them we can intercept actions before or after achieve it: I.e. a Save, Update, Load, Flush and others.

At this example we gonna define the EventListener make the override from a Default base class. This could be done implementing interfaces.

public class MySaveEventListener : NHibernate.Event.Default.DefaultSaveOrUpdateEventListener
{
    protected override void CascadeBeforeSave(IEventSource source, IEntityPersister persister,
                                              object entity, object anything)
    {
        Console.WriteLine("Before Save the entity " + entity);
        base.CascadeBeforeSave(source,persister,entity,anything);
    }

    protected override void CascadeAfterSave(IEventSource source, IEntityPersister persister,
                                             object entity, object anything)
    {
        Console.WriteLine("After Save the entity " + entity);
        base.CascadeAfterSave(source,persister,entity,anything);
    }
}

The ISessionFactory programatic configuration could be done like this:

Configuration cfg = new Configuration();

cfg.Configure("hibernate.cfg.xml");

cfg.SetListener(ListenerType.Save, new MySaveEventListener());

Now we do the Save operation:

using (ISessionFactory sf = cfg.BuildSessionFactory())
{
    using (ISession session = sf.OpenSession())
    {
        Foo f1 = new Foo();
        f1.Misc = "m1";
        f1.Name = "n1";

        session.Save(f1);

        session.Flush();
    }
}

This is the console output, including the SQL generated by NHibernate:

Before Save the entity Entity Foo:0:n1
NHibernate: INSERT INTO Foo (Name, Misc) VALUES (@p0, @p1); select SCOPE_IDENTIT
Y(); @p0 = 'n1', @p1 = 'm1'
After Save the entity Entity Foo:1:n1

Foo object has it’s Integer and Identity. Before Save the Id Property has the 0 (zero) value, after Save the value was changed to 1 (because it’s the first object at base).

Rhino Mocks Syntax

Rhino Mocks it’s an excelent framework for mocking to use in our unit testings. One reason to use it is that do not make use of strings to hardcoding the names of types, methods, properties, etc, reducing the error posibilities at runtime.

After of 3.0.5 version released some time ago, the sintax became more easier to read and with less probabilities on errors.

At look this introductory screencast you’ll see how to do a typical mocking, and using the standart way to do it. The posibilities to forget the call VerifyCall() method exists.

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            Expect
                    .Call(net.Value)
                    .Return(5.0);
            

            Mocks.ReplayAll();
            
                //f'(net) = y * ( 1 - y )
                Assert.Equal(0.006648057, Math.Round(tf.Derivate(net), 9));

            Mocks.VerifyAll();
        }

One way to do it more crearly and safety:

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            using (Mocks.Record())
            {
                Expect
                    .Call(net.Value)
                    .Return(5.0);
            }

            using (Mocks.Playback())
            {
                //f'(net) = y * ( 1 - y )
                Assert.Equal(0.006648057, Math.Round(tf.Derivate(net), 9));
            }
        }

 

On this examples I’m using a helper for the Mock<T>() method and the MockRepository Mocks {get;set;}. Nothing unusual so far.

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            using (Mocks.Record())
            {
                Expect
                    .Call(net.Value)
                    .Return(5.0);
            }

            using (Mocks.Playback())
            {
                //f'(net) = y * ( 1 - y )
                Assert.Equal(0.006648057, Math.Round(tf.Derivate(net), 9));
            }
        }

There is another way to do the same but using delegates instead of keyword using: The With class (actually I think that I know where it come from).

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            With
                .Mocks(Mocks)
                .Expecting(delegate
                               {
                                   Expect
                                       .Call(net.Value)
                                       .Return(5.0);
                               })
                .Verify(delegate
                            {
                                //f'(net) = y * ( 1 - y )
                                Assert.Equal(0.006648057, 
                                    Math.Round(tf.Derivate(net), 9));
                            });
        }

I prefer the 2nd option.