NHibernate温莎每个请求的实现

本文关键字:请求 实现 NHibernate | 更新日期: 2023-09-27 18:11:34

我在我的项目中使用了NHibernate和Castle Windsor Injection。我的NHibernate实现是这样的:

Component.For<ISessionFactory>().UsingFactoryMethod(CreateSessionFactory).LifestyleSingleton(),
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>().LifestyleSingleton(),
Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession()).LifestylePerWebRequest(),

如果我想双击刷新页面或在新选项卡上打开某些页面,我会得到错误

ExecuteReader需要一个打开且可用的连接。连接的当前状态是关闭的。

我的实现有什么错误吗?怎么了?怎么解呢?

这是UnitOfWork类:公共单位工作电流{得到{If (_current == null)_current = new UnitOfWork(sessionFactory, Session);返回_current;}}(ThreadStatic)private UnitOfWork _current

    /// <summary>
    /// Gets Nhibernate session object to perform queries.
    /// </summary>
    public ISession Session { get; get; }
    /// <summary>
    /// Reference to the session factory.
    /// </summary>
    private readonly ISessionFactory sessionFactory;
    /// <summary>
    /// Reference to the currently running transcation.
    /// </summary>
    private ITransaction transaction;
    /// <summary>
    /// Creates a new instance of NhUnitOfWork.
    /// </summary>
    /// <param name="sessionFactory"></param>
    public UnitOfWork(ISessionFactory _sessionFactory, ISession _session)
    {
        sessionFactory = _sessionFactory;
        Session = _session;
    }
    /// <summary>
    /// Opens database connection and begins transaction.
    /// </summary>
    public void BeginTransaction(IsolationLevel isoLevel=IsolationLevel.ReadCommitted)
    {
        transaction = Session.BeginTransaction(isoLevel);
    }
    /// <summary>
    /// Commits transaction and closes database connection.
    /// </summary>
    public void Commit()
    {
        transaction.Commit();
    }
    /// <summary>
    /// Rollbacks transaction and closes database connection.
    /// </summary>
    public void Rollback()
    {
        transaction.Rollback();
    }
    public void Dispose()
    {
        //Session.Dispose();
    }

NHibernate温莎每个请求的实现

如果您在web项目中这样做,并且您的PerWebRequest windsor Lifestyle建议,我会摆脱您的工作实现单元,并直接处理来自global .asax的请求事件。在web中,工作单元是请求。我还喜欢使用安装程序来连接Windsor。这是一个适合我的配置。

public class MvcApplication : HttpApplication
{
    private const String Sessionkey = "current.session";
    private static IWindsorContainer Container { get; set; }
    private static ISessionFactory SessionFactory { get; set; }
    public static ISession CurrentSession
    {
        get { return (ISession) HttpContext.Current.Items[Sessionkey]; }
        private set { HttpContext.Current.Items[Sessionkey] = value; }
    }
    protected void Application_Start()
    {
        Version version = Assembly.GetExecutingAssembly().GetName().Version;
        Application["Version"] = String.Format("{0}.{1}", version.Major, version.Minor);
        Application["Name"] = ConfigurationManager.AppSettings["ApplicationName"];
        //create empty container
        //scan this assembly for any installers to register services/components with Windsor
        Container = new WindsorContainer().Install(FromAssembly.This());
        //API controllers use the dependency resolver and need to be initialized differently than the mvc controllers
        GlobalConfiguration.Configuration.DependencyResolver = new WindsorDependencyResolver(Container.Kernel);
        //tell ASP.NET to get its controllers from Castle
        ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container.Kernel));
        //initialize NHibernate
        ConnectionStringSettings connectionString = ConfigurationManager.ConnectionStrings[Environment.MachineName];
        if (connectionString == null)
            throw new ConfigurationErrorsException(String.Format("Connection string {0} is empty.",
                Environment.MachineName));
        if (String.IsNullOrWhiteSpace(connectionString.ConnectionString))
            throw new ConfigurationErrorsException(String.Format("Connection string {0} is empty.",
                Environment.MachineName));
        string mappingAssemblyName = ConfigurationManager.AppSettings["NHibernate.Mapping.Assembly"];
        if (String.IsNullOrWhiteSpace(mappingAssemblyName))
            throw new ConfigurationErrorsException(
                "NHibernate.Mapping.Assembly key not set in application config file.");
        var nh = new NHInit(connectionString.ConnectionString, mappingAssemblyName);
        nh.Initialize();
         SessionFactory = nh.SessionFactory;
        AutoMapConfig.RegisterMaps();
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        ModelBinderConfig.RegisterModelBinders(ModelBinders.Binders);
        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
    }
    protected void Application_OnEnd()
    {
        //dispose Castle container and all the stuff it contains
        Container.Dispose();
    }
    protected void Application_BeginRequest() { CurrentSession = SessionFactory.OpenSession(); }
    protected void Application_EndRequest()
    {
        if (CurrentSession != null)
            CurrentSession.Dispose();
    }

}}

这是我的NhInit类

public class NHInit : NHibernateInitializer
{
    public NHInit(String connectionString, String mappingAssemblyName) : base(connectionString, mappingAssemblyName)
    {
    }
}

NHibernateInitializer

public abstract class NHibernateInitializer : IDomainMapper
{
    protected Configuration Configure;
    private ISessionFactory _sessionFactory;
    private readonly ModelMapper _mapper = new ModelMapper();
    private Assembly _mappingAssembly;
    private readonly String _mappingAssemblyName;
    private readonly String _connectionString;
    protected NHibernateInitializer(String connectionString, String mappingAssemblyName)
    {
        if (String.IsNullOrWhiteSpace(connectionString))
            throw new ArgumentNullException("connectionString", "connectionString is empty.");
        if (String.IsNullOrWhiteSpace(mappingAssemblyName))
            throw new ArgumentNullException("mappingAssemblyName", "mappingAssemblyName is empty.");
        _mappingAssemblyName = mappingAssemblyName;
        _connectionString = connectionString;
    }
    public ISessionFactory SessionFactory
    {
        get
        {
            return _sessionFactory ?? (_sessionFactory = Configure.BuildSessionFactory());
        }
    }
    private Assembly MappingAssembly
    {
        get
        {
            return _mappingAssembly ?? (_mappingAssembly = Assembly.Load(_mappingAssemblyName));
        }
    }
    public void Initialize()
    {
        Configure = new Configuration();
        Configure.EventListeners.PreInsertEventListeners = new IPreInsertEventListener[] { new EventListener() };
        Configure.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[] { new EventListener() };
        Configure.SessionFactoryName(System.Configuration.ConfigurationManager.AppSettings["SessionFactoryName"]);
        Configure.DataBaseIntegration(db =>
                                      {
                                          db.Dialect<MsSql2008Dialect>();
                                          db.Driver<SqlClientDriver>();
                                          db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
                                          db.IsolationLevel = IsolationLevel.ReadCommitted;
                                          db.ConnectionString = _connectionString;
                                          db.BatchSize = 20;
                                          db.Timeout = 10;
                                          db.HqlToSqlSubstitutions = "true 1, false 0, yes 'Y', no 'N'";
                                      });
        Configure.SessionFactory().GenerateStatistics();
        Map();
    }
    public virtual void InitializeAudit()
    {
        var enversConf = new Envers.Configuration.Fluent.FluentConfiguration();
        enversConf.Audit(GetDomainEntities());
        Configure.IntegrateWithEnvers(enversConf);
    }
    public void CreateSchema()
    {
        new SchemaExport(Configure).Create(false, true);
    }
    public void DropSchema()
    {
        new SchemaExport(Configure).Drop(false, true);
    }
    private void Map()
    {
        _mapper.AddMappings(MappingAssembly.GetExportedTypes());
        Configure.AddDeserializedMapping(_mapper.CompileMappingForAllExplicitlyAddedEntities(), "MyWholeDomain");
    }
    public HbmMapping HbmMapping
    {
        get { return _mapper.CompileMappingFor(MappingAssembly.GetExportedTypes()); }
    }
    public IList<HbmMapping> HbmMappings
    {
        get { return _mapper.CompileMappingForEach(MappingAssembly.GetExportedTypes()).ToList(); }
    }
    /// <summary>
    /// Gets the domain entities.
    /// </summary>
    /// <returns></returns>
    /// <remarks>by default anything that derives from EntityBase and isn't abstract or generic</remarks>
    protected virtual IEnumerable<System.Type> GetDomainEntities()
    {
        List<System.Type> domainEntities = (from t in MappingAssembly.GetExportedTypes()
                                            where typeof(EntityBase<Guid>).IsAssignableFrom(t)
                                            && (!t.IsGenericType || !t.IsAbstract)
                                            select t
                                           ).ToList();
        return domainEntities;
    }
}

SessionInstaller

public class SessionInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container
            .Register(Component.For<ISession>().UsingFactoryMethod(() => MvcApplication.CurrentSession)
                .LifeStyle
                .PerWebRequest);
    }
}

ControllersInstaller

public class ControllersInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
            .BasedOn<IController>()
            .LifestyleTransient());
    }
}

控制器工厂
public class WindsorControllerFactory : DefaultControllerFactory
{
    // Fields
    private readonly IKernel _kernel;
    // Methods
    public WindsorControllerFactory(IKernel kernel)
    {
        if (kernel == null)
            throw new ArgumentNullException("kernel");
        _kernel = kernel;
    }
    protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType == null)
            throw new HttpException(0x194,
                string.Format(
                    "The controller for path '{0}' could not be found or it does not implement IController.",
                    context.HttpContext.Request.Path));
        return (IController) _kernel.Resolve(controllerType);
    }
}