Sunday, May 12, 2013

NHibernate 3.x changes


Working on a sample project for a perspective company - when enabled NuGet for FluentNHibernate, and saw a breaking change in the NhQueryable constructor. (I've been building from the source for awhile so this one passed me by, 2.x - 3.x introduced some breaking changes)

This breaks:
...
public ReadOnlyRepository(ISession session)
        {
            this.selection = new NhQueryable(session);
        }
....

This 'seemed' to work - at least the compiler didn't complain:
...

public ReadOnlyRepository(ISession session)
        {
            this.selection = new NhQueryable(session as ISessionImplementor);
        }
...

After a few unit-tests later I discover that the session passed in is NOT being preserved. Now what?

So I look at the IQueryOver interface - inside of Hibernate seems to add some Extension methods and a Linq-like interface; but I miss the more "natural" feel of regular Linq expressions. Granted, I won't have as much fine-control over the underlying query - but I'm not doing anything too crazy - yet.

I end-up changing the original interface/implementation from:
 public interface IReadOnlyRepository where TEntity : class  
  {  
      IQueryable Linq();  
  }  
...
#region IReadOnlyRepository Members

         public IQueryable Linq()
  {
   return this.selection.AsQueryable();
  }

#endregion
...

to the 3.x friendly:

public interface IReadOnlyRepository : IQueryable where TEntity : class
    {
        IQueryable AsQueryable(); 
    }
...

Note: The implementation then explicitly marshals the "queryable-ness" to my preserved session.

Also Note: the explicit usage of namespace System.Linq - otherwise it WILL conflict with Hibernate:

#region IReadOnlyRepository Members

        public System.Linq.IQueryProvider Provider
        {
            get { return session.Query().Provider; }
        }

        public System.Collections.Generic.IEnumerator GetEnumerator()
        {
            return session.Query().GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public System.Type ElementType
        {
            get { return session.Query().ElementType; }
        }

       public System.Linq.Expressions.Expression Expression
        {
            get { return session.Query().Expression; }
        }

        public IQueryable AsQueryable()
        {
            return session.Query();
        }
        #endregion

Turns out this tripped out quite a few, as I searched the web. Hope this helps someone transitioning from building from source to moving to NuGet.

No comments: