nhibernate/structuremap ObjectFactory.GetInstance ISession失败

nhibernate/structuremap ObjectFactory.GetInstance ISession失败,nhibernate,session,structuremap,Nhibernate,Session,Structuremap,我正在使用asp.NETMVC应用程序,它工作得很好。但当我在全局过滤器中使用它时: public class CustomActionFilter: ActionFilterAttribute { public ISession Session { get; set; } public CustomActionFilter() { this.Session = ObjectFactory.GetInstance<ISession>();

我正在使用asp.NETMVC应用程序,它工作得很好。但当我在全局过滤器中使用它时:

public class CustomActionFilter: ActionFilterAttribute
{
    public ISession Session { get; set; }

    public CustomActionFilter()
    {
        this.Session = ObjectFactory.GetInstance<ISession>();
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //call ISession.CreateQuery(...); query.UniqueResult<SomeObject>();

    }        
}
公共类CustomActionFilter:ActionFilterAttribute
{
公共ISession会话{get;set;}
公共CustomActionFilter()
{
this.Session=ObjectFactory.GetInstance();
}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
//调用ISession.CreateQuery(…);query.UniqueResult();
}        
}
这将导致“会话关闭”错误。我做错了什么,有什么线索吗


提前谢谢

首先,我忽略了关于全局过滤器的一点

当然,这取决于您如何实例化过滤器

  • 当您将筛选器定义为属性时,它将在运行时控制器操作调用期间实例化,并轻松注入当前可用的
    ISession
    实例
  • 但是,当您尝试将其添加到
    GlobalFilterCollection
    时,您必须(默认情况下)像这样实例化它:
    filters.add(new CustomActionFilter())
    。这意味着
    CustomActionFilter
    构造函数将立即被调用(在应用程序启动时),并尝试解析会话。正如您所想象的,您不能对MVC应用程序的所有请求使用相同的
    ISession
    。因此,您可以实现每个请求的会话模式。并且应该为每个请求注入新实例
最简单的方法是将ISession(
this.Session=ObjectFactory.GetInstance();
移动到
OnActionExecuting(…)
方法

更复杂的方法是创建自己的
CustomFilterCollection
类型并提供自己的过滤器注册基础结构

更新:第一个建议的解决方案不适用。问题是筛选器在其属性中存储状态。尽管有以下选项:

  • 将过滤器用作属性,而不是
    GlobalFilterCollection
    元素
  • 在筛选器本身内部实现状态并发控制(即,在全局筛选器的集合属性中为所有请求存储
    会话
    ,并以某种方式对其进行管理)。糟糕、难闻的方法imho,且不可扩展。会话生存期管理不应属于筛选器
  • 使用不同的过滤器注册系统(即,滚动您自己的
    IFilterProvider
    ——以如何执行为例;或者仅使用它)

另外,最好将
ActionFilter
s与
filteratribute
s分离。

请您,plz,为
ISession
,以及与NHibernate会话管理相关的所有其他内容,提供多一点StructureMap注册代码。如果在同一时间有两个请求使用该筛选器,是否会有进一步的复杂性同一时间?其中一个可能在第二个请求完成处理之前关闭会话。是的,看起来你是对的。此外,
“其中一个可能在第二个请求完成处理之前关闭会话”
完全是错误的-两个不同的请求不应该使用同一会话(除了某些特定的“DB对话”)场景)。您的操作筛选器属性存储状态(ISession)-这就是问题所在。您可以将此类筛选器用作属性,也可以将实际筛选器与属性解耦(在MVC3中,筛选器不再需要是属性)。最好的选择是使用类似的方法。这样,您可以只定义筛选器的类型,但实际筛选器将根据每个请求进行实例化。