0

そうです、Session.SaveOrUpdate(entity)の後にSession.Flush()を明示的に呼び出さなくても、非常に簡単にアイテムを作成できますが、これは更新または削除には当てはまりません。Session.Flush()と入力する代わりに、Session.Transaction.Commit()と入力して、同じ効果(つまり、即時削除/更新)を実現することもできます。

これにより、NHibernateActionFilterトランザクションの処理に問題があると思います。つまり、常にコミットするのではなく、一部の時間しかコミットしません。理由がよくわかりませんか?

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();
        }
    }
}
4

1 に答える 1

1

明示的なトランザクションがないと、ID列のマッピング方法によっては、NHibernateでInsertがすぐに起動する場合があります。これは、NHibernateがSave / SaveOrUpdateを呼び出した後、エンティティに有効なId値を持たせたいためです。「identity」のようなデータベース生成戦略は、SaveOrUpdateの実行時にすぐに起動する必要がありますが、「guid」のような戦略は、フラッシュするまで待機します。

投稿したコードは一見問題ないように見えるので、アクションフィルターの配線方法に問題がある可能性があります。説明する動作は、フィルターがまったく呼び出されないこととも一致します(ただし、その場合、セッションが開いている理由はわかりません)。

于 2012-08-11T11:41:47.480 に答える