【发布时间】:2014-03-04 06:59:13
【问题描述】:
我已经使用 Autofac 成功实现了 Session-per-HttpRequest。
我对我的实现不满意,因为我正在经历DependencyResolver 并且不依赖于 AutoFac 提供的参数。如果我依赖 AutoFac 提供的 ISession 参数,那么我会收到一条带有 NHProf 的警告,表明有多个会话正在使用中。如果我通过DependencyResolver,来自NHProf 的警告就会消失,但我觉得用法不正确。
我已遵循此处列出的 Autofac + MVC4.0 指南:https://code.google.com/p/autofac/wiki/MvcIntegration
我也将本指南用作参考。表示应该可以接受ISession作为构造函数参数:http://slynetblog.blogspot.com/2011/04/lightweight-nhibernate-and-aspnet-mvc.html
这是我构建 Autofac 容器的方法:
public class AutofacRegistrations
{
public static void RegisterAndSetResolver()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterControllers(Assembly.GetExecutingAssembly());
// Only generate one SessionFactory ever because it is expensive.
containerBuilder.Register(x => new NHibernateConfiguration().Configure().BuildSessionFactory()).SingleInstance();
// Everything else wants an instance of Session per HTTP request, so indicate that:
containerBuilder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).As<ISession>().InstancePerHttpRequest();
containerBuilder.Register(x => LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType)).As<ILog>().InstancePerHttpRequest();
containerBuilder.RegisterType<NHibernateDaoFactory>().As<IDaoFactory>().InstancePerHttpRequest();
containerBuilder.RegisterType<StreamusManagerFactory>().As<IManagerFactory>().InstancePerHttpRequest();
// containerBuilder.RegisterModule adds all the required http modules to support per web request lifestyle and change default controller factory to the one that uses Autofac.
containerBuilder.RegisterModule(new AutofacWebTypesModule());
IContainer container = containerBuilder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
这是我的基本控制器类。注意原始接受会话作为参数的注释掉的代码:
public abstract class StreamusController : Controller
{
protected readonly ILog Logger;
protected new readonly ISession Session;
protected StreamusController(ILog logger, /*ISession session*/)
{
if (logger == null) throw new ArgumentNullException("logger");
//if (session == null) throw new ArgumentNullException("session");
Logger = logger;
// TODO: Is this different than passing ISession into Controller with AutoFac?
Session = DependencyResolver.Current.GetService<ISession>();
//Session = session;
}
}
根据我是使用 ISession 作为参数还是通过 DependencyResolver 访问它,我在使用 NHProf 时遇到了不同的结果。为什么?我的理解是这两种方式应该是完全一样的!
作为参考,这是我的 Lazy NHibernateConfiguration/ISessionFactory 实现。我不认为它与手头的问题非常相关:
public class NHibernateConfiguration
{
public FluentConfiguration Configure()
{
string connectionString = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
FluentConfiguration fluentConfiguration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString).ShowSql().FormatSql())
.Mappings(cfg => cfg.FluentMappings.AddFromAssemblyOf<UserMapping>())
.ExposeConfiguration(ConfigureStreamusDataAccess);
return fluentConfiguration;
}
private static void ConfigureStreamusDataAccess(Configuration configuration)
{
// NHibernate.Context.WebSessionContext - analogous to ManagedWebSessionContext above, stores the current session in HttpContext.
// You are responsible to bind and unbind an ISession instance with static methods of class CurrentSessionContext.
configuration.SetProperty("current_session_context_class", "web");
configuration.SetProperty("connection.isolation", "ReadUncommitted");
configuration.SetProperty("default_schema", "[Streamus].[dbo]");
configuration.SetProperty("generate_statistics", "true");
}
}
这里是 NProf 的屏幕截图,表明我的 CreateMultiple 操作中有多个会话,而另一个屏幕截图没有表明多个会话。第一张截图使用ISession作为参数传入,第二张截图使用DependencyResolver:
【问题讨论】:
标签: c# session nhibernate autofac