Reputation: 679
Yeah so I can quite easily create items without having to explicitly call Session.Flush() after Session.SaveOrUpdate(entity) - but this isn't true with updating or deleting. Instead of typing Session.Flush() I can also type Session.Transaction.Commit() to achieve the same effect (i.e, instant deletion / update).
This leads me to believe there's a problem with my NHibernateActionFilter transaction handling, i.e., it only commits some of the time instead of all the time. I'm not quite sure why?
BrandController : SessionController
[HttpPost]
public ActionResult Edit (EditBrandViewModel editBrandViewModel)
{
if(ModelState.IsValid)
{
var model = editBrandViewModel;
var brand = Session.Get<Brand>(model.Id);
Mapper.Map(model, brand);
Session.SaveOrUpdate(brand);
Session.Flush();
return RedirectToAction("Details/" + model.Id);
}
return View(editBrandViewModel);
}
public ActionResult Delete(int id)
{
var brand = Session.Get<Brand>(id);
Session.Delete(brand);
Session.Flush();
return RedirectToAction("Index");
}
SessionController:
public class SessionController : Controller
{
public HttpSessionStateBase HttpSession
{
get { return base.Session; }
}
public new ISession Session { get; set; }
}
NHibernateActionFilter:
public class NHibernateActionFilter : ActionFilterAttribute
{
private static ISessionFactory sessionFactory;
public NHibernateActionFilter(ISessionFactory sessionFactory)
{
sessionFactory = sessionFactory;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var sessionController = filterContext.Controller as SessionController;
if (sessionController == null)
return;
sessionController.Session = sessionFactory.OpenSession();
sessionController.Session.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var sessionController = filterContext.Controller as SessionController;
if (sessionController == null)
return;
using (var session = sessionController.Session)
{
if (session == null)
return;
if (!session.Transaction.IsActive)
return;
if (filterContext.Exception != null)
session.Transaction.Rollback();
else
session.Transaction.Commit();
}
}
}
Upvotes: 0
Views: 363
Reputation: 56
Without an explicit transaction, Inserts might fire immediately in NHibernate depending on how you mapped the identity column. This is because NHibernate wants his/her entities to have a valid Id value after calling Save/SaveOrUpdate. A database generated strategy like "identity" will have to fire it immediately when executing SaveOrUpdate, but a strategy like "guid" will wait until you flush.
The code you posted looks ok on first glance, so the problem might be in how the action-filter is wired. The behaviour you describe would also be consistent with your filter never being called at all (though in that case I wouldn't know why the session is open).
Upvotes: 1