2

I have this situation:

I'm using Nhibernate to map an Entity 'User' that is mapped on a large table in Sql, for perfomance reasons I've created a lightweight entity 'LightweightUser' that has only a small set of properties and is NOT mapped in a hbm file or whatever, I'm using the Nhibernate Projection technique to wire the 'LightweightUser' entity. Both entities are deriving from a simple class 'Entity' that contains an Id property.

The above implementations works fine, sql query is smaller == faster.

But in my Nhibernate SessionFactory I have also injected a Nhibernate Intercerptor. The OnLoad method of the Interceptor is called when I'm getting a 'User' entity from the NHibernate Dao, but when I get the 'LightweightUser' entity from the NHibernate Dao the Interceptor is not triggered (OnLoad method).

This is probably related to the fact that NHibernate SessionFactory has no knowledge of my 'LightweightUser' entity. Is there a way to inform the Sessionfactory/ Interceptor of the existence of my 'Lightweight' entity? Or is there some other technique to wire Projections to an Interceptor? And yes I can also duplicate the the 'hbm' file for my Lightweight entity, but that seems like bad practice.

    [TestFixture]
    public class InterceptorTest : NhibernateSessionHelper
    {
    [Test]
    public void GetEntiy()
    {
        //ok trigger OnLoad in the Interceptor
        var user = GetSession().Get<User>(1);
        Assert.IsNotNull(user);
    }

    [Test]
    public void GetProjection()
    {
        var crit = GetSession().CreateCriteria<User>();
        crit.Add(Restrictions.Eq("Id", 5));
        crit.SetProjection(Projections.ProjectionList()
                                      .Add(Projections.Property("Id"), "Id")
                                      .Add(Projections.Property("Username"), "UserName"));

        crit.SetResultTransformer(Transformers.AliasToBean(typeof(LightweightUser)));

        //does not trigger the Interceptor
        var result = crit.List<LightweightUser>();

        Assert.IsNotNull(result.First());

    }
} 


    //Wire the Sessionfactory with Interceptor
    private static ISessionFactory CreateSessionFactory()
    {
        return new Configuration()
        .CurrentSessionContext<ThreadStaticSessionContext>()
        .SetInterceptor(new MyInterceptor())
            .Configure().BuildSessionFactory();
    }


 public class MyInterceptor: IInterceptor
{
    public override bool OnLoad(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
    {
        //do stuff

        var s = entity;
        return base.OnLoad(entity, id, state, propertyNames, types);
    }

Thanks in advance

1 Answers1

2

The Interceptor's method OnLoad is called only in handling of PreLoadEvent. This is raised in two cases: when an entity is loaded from the database, or when the entity is assembled from the cache. Objects created with a projection like yours are not considered being an entity.

If you want to apply the same code for entities and for tuples of LightweightUser you can implement your custom IResultTransformer containing an instance of

Transformers.AliasToBean(typeof(LightweightUser))

and after calling the original transformer methods apply your logic of

//do stuff

If want to know more about interceptor, I encourage you to read a list of my blog entries starting here: http://blog.scooletz.com/2011/02/03/nhibernate-interceptor-magic-tricks-pt-1/

Scooletz
  • 183
  • 2
  • 7