Reputation: 70022
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;
}
}
Upvotes: 1
Views: 1005
Reputation: 26940
You need to use the same ISession for that request, hence the InRequestScope()
. You could change NHibernateSession.Current to something like return DependencyResolver.Current.GetService<ISession>();
but it's probably more preferred to ctor inject the ISession into the FilterAttribute and tell ninject about it with this.BindFilter<UnitOfWorkFilter>(FilterScope.Action, 0);
https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations
Upvotes: 1
Reputation: 4479
From your comment on your question, I think each time you call NHibernateSession.Current
you're getting a new session. That's the problem. Your session needs to have per-web-request lifetime semantics. You'll want to inject the session into your controller or your filter.
Upvotes: 1