Kiada
Kiada

Reputation: 679

Is having to explicitly call Session.Flush() after updates and deletes a sign of a bigger issue with my application?

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

Answers (1)

Tom Kemper
Tom Kemper

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

Related Questions