NHibernate中Session与ASP.NET MVC中Action的综合使用

2024-02-15 17:48

本文主要是介绍NHibernate中Session与ASP.NET MVC中Action的综合使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

NHibernate的基本特征是完成面向对象的程序设计语言到关系数据库的映射,在NHibernate中使用持久化对象PO(Persistent Object)完成持久化操作,对PO的操作必须在Session管理下才能同步到数据库, 但是这里的Session并非指HttpSession,可以理解为基于ADO.NET的Connnection,Session是NHibernate运作的中心,对象的生命周期、事务的管理、数据库的存取都与Session息息相关,首先,我们需要知道, SessionFactory负责创建Session,SessionFactory是线程安全的,多个并发线程可以同时访问一个SessionFactory 并从中获取Session实例。 只有一个数据存储源(数据库),只需创建一个SessionFactory,SessionFactory就是个重量级对象,如果应用只有一个数据存储源,只需创建一个SessionFactory实例,因为随意地创建SessionFactory实例会占用大量内存空间。这里所说的只创建一个,通常是使用单例模式,使本次应用程序域中的所有请求都访问同一个SessionFactory.但是他的实例session是轻量级的。而Session并非线程安全,也就是说,如果多个线程同时使用一个Session实例进行数据存取,则将会导致Session 数据存取逻辑混乱.因此创建的Session实例必须在本地存取空上运行,使之总与当前的线程相关。而Session并非线程安全,也就是说,如果多个线程同时使用一个Session实例进行数据存取,则将会导致 Session 数据存取逻辑混乱.因此创建的Session实例必须在本地存取空上运行, 使之总与当前的线程相关。


多个线程中(即多个request中)不能使用一个Session,但一个request中可能存在多个Session,不从性能角度考虑,这样也是不会报错的,就像ADO.NET的时候,在一个方法中同时创建了两个Connection来操作同一个数据库一样,虽然性能有问题,但是还是能实现操作的。注意,如果涉及到了Transaction事务处理,那就必须在同一个Session中完成。


为了保证一个浏览器访问,也就是一次request,使用的都是各自的Session,在Java(Hibernate)中,ThreadLocal 是Java中一种较为特殊的线程绑定机制,通过ThreadLocal存取的数据, 总是与当前线程相关, 也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种隔离机,ThreadLocal并不是线程本地化的实现,而是线程局部变量。也就是说每个使用该变量的线程都必须为该变量提供一个副本,每个线程改变该变量的值仅仅是改变该副本的值,而不会影响其他线程的该变量的值,ThreadLocal是隔离多个线程的数据共享,不存在多个线程之间共享资源,因此不再需要对线程同步。

ASP.NET MVC中,通常会结合Controller使用。一般是在controller中调用各个domain的service方法最终进行了数据库的各种操作,所以我们只要在controller的action执行之前,把一个新的session绑定到当前的线程就可以了,本次request流程中,所有对于数据库的操作,都使用这个Session.

    AttributeUsageAttribute(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]public class NHibernateSessionAttribute : FilterAttribute, IActionFilter{public NHibernateSessionAttribute() : base(){}public void OnActionExecuting(ActionExecutingContext filterContext){var session = SessionProvider.GetNewSession();//这里是获取了一个新的Session.因为这里是每次操作刚刚开始的设计NHibernateCurrentSessionContext.Bind(session);//打开一个新的Session,放入到当前上下文中,以后再用Session的时候GetCurrentSession就可以}public void  OnActionExecuted(ActionExecutedContext filterContext){CurrentSessionContext.Unbind(SessionProvider.GetSessionFactory()).Close();}
在使用的时候,只需要在Action上边加一个NHibernateSession的Filter,就可以在这个Action执行前,先执行这个Filter的内容,绑定Session,然后完事后,在解除Session

        [NHibernateSession]public ActionResult SaveNewOrder(Order order){......return RedirectToAction("Index");}

SessionProvider用户管理Session的获取,是一个静态类,保证了SessionFactory唯一性,这样做比较考虑性能。

    public class SessionProvider{private static ISessionFactory sessionFactory;public static NHibernate.Cfg.Configuration configuration;static SessionProvider(){configuration = new NHibernate.Cfg.Configuration().Configure();sessionFactory = configuration.BuildSessionFactory();}public static ISessionFactory GetSessionFactory(){return sessionFactory;}public static ISession GetNewSession(){return sessionFactory.OpenSession(); //这个方法一般是首次用到Session的时候,然后绑定到上下文中}public static ISession GetNewOrCurrentSession() {ISession session = null;if (!CurrentSessionContext.HasBind(sessionFactory)){session = sessionFactory.OpenSession();CurrentSessionContext.Bind(session);}else{session = sessionFactory.GetCurrentSession();if (!session.IsOpen)session = sessionFactory.OpenSession();}return session;}}

注意:如果我们在建立Windwos Service的时候,就没有了Action中的那个绑定以及解绑的过程。这里的Session是Thread_Static的,所以一用到Session的时候,就会直接到Session = SessionProvider.GetNewOrCurrentSession中来获取。但是注意,这里并没有一个解除绑定的过程。在ASP.NET MVC的是,unbind的时候,会自动调用Flush方法,然后去更新数据库。而如果我们在Windows Service程序中不手动调用Session.Flush去更新数据库,一切操作是没有同步到数据库中的。当这个线程结束,Session消失,一切操作都没有同步。所以,我们要记得手动去调用Flush方法。

这篇关于NHibernate中Session与ASP.NET MVC中Action的综合使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/712091

相关文章

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

Jsoncpp的安装与使用方式

《Jsoncpp的安装与使用方式》JsonCpp是一个用于解析和生成JSON数据的C++库,它支持解析JSON文件或字符串到C++对象,以及将C++对象序列化回JSON格式,安装JsonCpp可以通过... 目录安装jsoncppJsoncpp的使用Value类构造函数检测保存的数据类型提取数据对json数

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

springboot整合 xxl-job及使用步骤

《springboot整合xxl-job及使用步骤》XXL-JOB是一个分布式任务调度平台,用于解决分布式系统中的任务调度和管理问题,文章详细介绍了XXL-JOB的架构,包括调度中心、执行器和Web... 目录一、xxl-job是什么二、使用步骤1. 下载并运行管理端代码2. 访问管理页面,确认是否启动成功

使用Nginx来共享文件的详细教程

《使用Nginx来共享文件的详细教程》有时我们想共享电脑上的某些文件,一个比较方便的做法是,开一个HTTP服务,指向文件所在的目录,这次我们用nginx来实现这个需求,本文将通过代码示例一步步教你使用... 在本教程中,我们将向您展示如何使用开源 Web 服务器 Nginx 设置文件共享服务器步骤 0 —

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Golang使用minio替代文件系统的实战教程

《Golang使用minio替代文件系统的实战教程》本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对... 目录文件系统 vs Minio文件系统不足:对象存储:miniogolang连接Minio配置Min

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画