nfplee
nfplee

Reputation: 7977

IStatelessSession With ISession Wrapper

I have wrapped the NHibernate session in my own IDataContext. My NHibernate implementation of this is as follows:

public class NHibernateDataContext : IDataContext {
    private readonly ISession _session;

    public NHibernateDataContext(ISession session) {
        _session = session;
        Begin();
    }

    public IRepository<T> Repository<T>() where T : class {
        return new NHibernateRepository<T>(_session);
    }

    public void Begin() {
        if (!_session.Transaction.IsActive)
            _session.BeginTransaction();
    }

    public void Commit() {
        if (_session.Transaction.IsActive)
            _session.Transaction.Commit();
    }

    public void Dispose() {
        _session.Close();
    }
}

public class NHibernateRepository<T> : IRepository<T> where T : class {
    private readonly ISession _session;

    public NHibernateRepository(ISession session) {
        _session = session;
    }

    public IQueryable<T> GetAll() {
        return _session.Query<T>();
    }

    public T GetByID(int id) {
        return _session.Get<T>(id);
    }

    public void Insert(T entity) {
        _session.SaveOrUpdate(entity);
    }

    public void Delete(T entity) {
        _session.Delete(entity);
    }
}

Using Microsoft Unity i then register this by saying:

// Configure the container
container.RegisterType<ISessionFactory>(new ContainerControlledLifetimeManager(), new InjectionFactory(c => {
    return CreateSessionFactory();
}));
container.RegisterType<ISession>(new InjectionFactory(c => {
    var sessionFactory = container.Resolve<ISessionFactory>();
    return sessionFactory.OpenSession();
}));
container.RegisterType<IDataContext, NHibernateDataContext>(new PerRequestLifetimeManager<IDataContext>());

So far so good, but my application needs to produce some large reports. I have found that they get exponentially slower due to the 1st level cache bloating. I understand the IStatelessSession interface allows me to do this.

How can i refactor my application so that i can easily use the IStatelessSession instead ISession when querying some data? Please note that for every request i would still like to have an ISession open, but only an IStatelessSession when i need it.

I'd appreciate the help. Thanks

Upvotes: 2

Views: 1715

Answers (1)

Dmitry
Dmitry

Reputation: 17350

IStatelessSession behavior is significantly different from ISession:

A stateless session does not implement a first-level cache nor interact with any second-level cache, nor does it implement transactional write-behind or automatic dirty checking, nor do operations cascade to associated instances. Collections are ignored by a stateless session. Operations performed via a stateless session bypass NHibernate's event model and interceptors. Stateless sessions are vulnerable to data aliasing effects, due to the lack of a first-level cache.

You can fight 1st level cache bloating by calling ISession.Clear periodically, say every 500 loaded objects. Otherwise you can just create a new 'context' (but be prepared for unexpected behavior).

public class NHibernateStatelessDataContext : IDataContext {
    private readonly IStatelessSession _session;
    ...
}

Upvotes: 3

Related Questions