I’m using Ninject, Fluent NHibernate and ASP.NET MVC.
Up until now everything has been working fine, I don’t get any errors and I’m able to query out of the repositories just fine, but I’m not able to commit any changes.
My controller method looks like this
[HttpPost]
[UnitOfWork]
public ActionResult Method(int id)
{
// Lookup entity, toggle a bool property on it and that is it
}
My UnitOfWork attribute looks like this
public class UnitOfWorkAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
NHibernateSession.Current.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null && NHibernateSession.Current.Transaction.IsActive)
{
NHibernateSession.Current.Transaction.Commit();
}
}
}
Both methods are being called and no errors are raised, the problem is that when NHibernateSession.Current (which just returns NHibernate.ISession) is called, ISession.IsDirty() is false. NHibernate doesn’t think anything has changed.
I’ve used similar setups in other projects before without a problem, the only difference with this one is that I swapped out StructureMap for Ninject, which I’m not that familiar with.
The relevant Bindings are
Bind<IEntityRepository>().To<EntityRepository>().InRequestScope();
Bind<ISessionFactory>().ToMethod(x => NHibernateSession.CreateSessionFactory()).InSingletonScope();
Bind<ISession>().ToMethod(x => x.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
Any ideas what I’ve done wrong? I’m guessing it has something to do with me messing up on the session handling, but I’m not sure exactly what.
Edit: This is what the Current call returns. The session should be stored so that a new session doesn’t have to be created each time.
public static ISession Current
{
get
{
var session = GetExistingSession();
if (session != null)
return session;
session = _sessionFactory.OpenSession();
HttpContext.Current.Items[SessionKey] = session;
return session;
}
}
You need to use the same ISession for that request, hence the
InRequestScope(). You could change NHibernateSession.Current to something likereturn DependencyResolver.Current.GetService<ISession>();but it’s probably more preferred to ctor inject the ISession into the FilterAttribute and tell ninject about it withthis.BindFilter<UnitOfWorkFilter>(FilterScope.Action, 0);https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations