如何在请求结束时在控制器内执行某些操作?

时间:2012-03-16 05:00:06

标签: c# asp.net-mvc-3 nhibernate

我想在控制器请求结束时处理NHibernate Session对象,即在渲染视图之后。我应该在哪里做?

3 个答案:

答案 0 :(得分:4)

您可以创建自己的custom action filter并覆盖OnResultExecuted

只是在控制器请求结束时作出反应,对NHibernate不太了解。

编辑:正如jgauffin所提到的,你也可以在控制器中覆盖OnResultExecuted。

答案 1 :(得分:0)

处理您的NHibernate会话不是您的控制器责任。理想情况下,在部署存储库时,它需要是您的存储库或/和您的IoCContainer。 与上面的答案相同,对NHibernate不太了解,但这就是我要遵循的那种模式。

答案 2 :(得分:0)

一篇很长的文章,但我做了一些事情: -

在我的global.asax.cs

public static ISessionFactory SessionFactory { get; set; }

然后在app start中定义

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);

    var nhConfig = new Configuration().Configure();
    SessionFactory = nhConfig.BuildSessionFactory();
}

然后创建此类: -

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class NHSession : ActionFilterAttribute
{
    public NHSession()
    {
        Order = 100;
    }

    protected ISessionFactory sessionFactory
    {
        get
        {
                return MvcApplication.SessionFactory;
        }
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var session = sessionFactory.OpenSession();
        CurrentSessionContext.Bind(session);
        session.BeginTransaction();
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var session = CurrentSessionContext.Unbind(sessionFactory);
        if (session != null)
        {
            if (session.Transaction.IsActive)
            {
                try
                {
                    session.Transaction.Commit();
                }
                catch
                {
                    session.Transaction.Rollback();
                }
            }
            session.Close();
        }
    }
}

然后我的通用存储库看起来像是: -

public class Repository<T> : IRepository<T>
{
    private readonly ISessionFactory SessionFactory;
    public Repository(ISessionFactory sessionFactory)
    {
        SessionFactory = sessionFactory;
    }
    public ISession Session
    {
        get
        {
            return SessionFactory.GetCurrentSession();
        }
    }
    public T Get(long id)
    {
        return Session.Get<T>(id);
    }
}

我对存储库的具体实现是: -

public class CmsContentRepository : Repository<CmsContent>, ICmsContentRepository
{
    public CmsContentRepository(ISessionFactory sessionFactory) : base(sessionFactory) { }
}

还有一件事我装饰我的控制器就像这样: -

[NHSession]
public ViewResult Revisions(int id)
{
    var model = Service.CmsContentRepository.Get(id);
    return View("Revisions", model);
}

这使我能够在请求中使用一个工作单元。基本上一个请求进来并启动一个会话,sessionfactory被传递到存储库的ctor ...我在这里使用DI,但这是可选的。如果检测到错误,则会话将回滚,如果没有在请求结束时提交。我会推荐NHProf,因为它可以帮助您理解会话管理(即如果没有正确设置)。