DDLLY命名空间
DDLLY命名空间有两个类DDL和LLY
博客园
首页
社区
联系
订阅
管理
随笔-81 评论-910 文章-0 trackbacks-56
NHibernate的Session管理
代码下载
看过hibernate文档的人应该看到在“
第 1 章 在Tomcat中快速上手
”,可以看到代码中使用ThreadLocal作为Session的存放容器。
public
static
final
ThreadLocal session
=
new
ThreadLocal();
查看
JDK的文档
,这个东东作用是给每个线程提供单独的静态变量,在一个线程内部共享,而不同的线程间不共享。
在hibernate中Session 是“单线程”的,即多个线程访问一个Session 会出问题。所以在最普遍的做法是一个操作就创建一个新的Session。Session对应着一个数据库的连接,而且Session内部提供了缓存(一级缓存)的机制。这样做意味这更多的数据库连接次数和缓存资源的浪费。
hibernate中使用使用ThreadLocal的目的就是让Session在一个线程内共享,尽可能的较少连接数据库的次数和尽可能的使用到一级缓存。
对于NHibernate是否有实现的办法呢。我们找到了
ThreadStaticAttribute
,它指示静态字段的值对于每个线程都是唯一的。用法如下
[ThreadStatic]
static
int
value;
似乎这样就可以了。在WinFrom,控制台应用程序和类库等中的确是没有问题了。但在Asp.Net中问题可不这么简单。在Java里Jsp作为Servlet来运行,是单线程的。而Asp.Net就不一样了,他用到了多个线程,造成的情况是:"当有多个线程的时候,ThreadStaticAttribute的变量被第一个线程初始化后,其它的线程访问到的都是null,而每个HttpRequest则可能有多个线程为其服务,因而有人称ThreadStatic is evil。"(此段引用
在ASP.NET中使用NHibernate - 风满袖 - 博客园
)。所以我们好的做法是使用HttpContext.Current.Items来共享session。使用HttpModule来处理之。在“
在ASP.NET中使用NHibernate - 风满袖 - 博客园
”里已经做了讲解。
我的想法是做一个统一的ISession提供者,只需要简单的配置即可用在不同的应用程序里。
储存ISession类需要实现的接口。
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
NHibernate;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
储存一个ISession
///
</summary>
public
interface
ISessionStorage
{
/**/
///
<summary>
///
获得ISession
///
</summary>
///
<returns></returns>
ISession Get();
/**/
///
<summary>
///
保存ISession
///
</summary>
///
<param name="value"></param>
void
Set(ISession value);
}
}
非Asp.Net程序使用的ISession提供者
/**/
/*
* 修改日期:2005-10-10
* 修改人:DDL
* 修改原因:
*
*/
using
System;
using
NHibernate;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
保存一个Session在一个thread-static的类成员中。
///
</summary>
public
class
ThreadSessionSource : ISessionStorage
{
[ThreadStatic]
private
static
ISession m_Session;
/**/
///
<summary>
///
获得Session
///
</summary>
///
<returns></returns>
public
ISession Get()
{
if
(m_Session
!=
null
)
{
if
(
!
m_Session.IsConnected)
{
m_Session.Reconnect();
}
}
return
m_Session;
}
/**/
///
<summary>
///
保存Session
///
</summary>
///
<param name="value"></param>
public
void
Set(ISession value)
{
if
(value.IsConnected)
{
value.Disconnect();
}
m_Session
=
value;
}
}
}
Asp.Net程序使用的ISession提供者
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
NHibernate;
using
System.Web;
using
Index.Data.NHibernateSessionStorage.CFG;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
储存一个ISession
<see cref="HttpContext.Items" />
集合.
///
</summary>
public
class
HttpSessionSource : ISessionStorage
{
/**/
///
<summary>
///
获得ISession
///
</summary>
///
<returns>
获得的ISession
</returns>
public
ISession Get()
{
return
(ISession)HttpContext.Current.Items[Config.HttpSessionSourceItemName];
}
/**/
///
<summary>
///
保存ISession
///
</summary>
///
<param name="value">
需要保存的ISession
</param>
public
void
Set(ISession value)
{
if
(value
!=
null
)
{
HttpContext.Current.Items.Add(Config.HttpSessionSourceItemName, value);
}
else
{
HttpContext.Current.Items.Remove(Config.HttpSessionSourceItemName);
}
}
}
}
通过读取配置文件让工厂提供不同的ISession提供者
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
System;
using
Index.Data.NHibernateSessionStorage.CFG;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
产生ISessionStorage的工厂
///
</summary>
public
class
ISessionStorageFactory
{
/**/
///
<summary>
///
获得ISessionStorage
///
</summary>
///
<returns></returns>
public
static
ISessionStorage GetSessionStorage()
{
if
(Config.SessionSourceType
==
"
http
"
)
//
使用
{
return
new
HttpSessionSource();
}
else
if
(Config.SessionSourceType
==
"
threadStatic
"
)
{
return
new
ThreadSessionSource();
}
else
{
throw
new
NotSupportedException(
"
不支持的SessionSourceType!
"
+
Config.SessionSourceType);
}
}
}
}
配置类
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
System;
using
System.Configuration;
namespace
Index.Data.NHibernateSessionStorage.CFG
{
/**/
///
<summary>
///
配置信息帮助类
///
</summary>
public
class
Config
{
私有成员
#region
私有成员
private
static
object
m_Locker
=
new
object
();
private
static
string
m_SessionSourceType
=
String.Empty;
private
static
string
m_HttpSessionSourceItemName
=
String.Empty;
#endregion
属性
#region
属性
/**/
///
<summary>
///
Session资源源类型;http,threadStatic
///
</summary>
public
static
string
SessionSourceType
{
get
{
lock
( m_Locker )
{
if
(m_SessionSourceType
==
String.Empty)
{
return
ConfigurationManager.AppSettings[
"
SessionSourceType
"
];
}
else
{
return
m_SessionSourceType;
}
}
}
}
/**/
///
<summary>
///
HttpSessionSource存放HttpContext.Current.Items的键值名
///
</summary>
public
static
string
HttpSessionSourceItemName
{
get
{
lock
( m_Locker )
{
if
(m_HttpSessionSourceItemName
==
String.Empty)
{
return
ConfigurationManager.AppSettings[
"
HttpSessionSourceItemName
"
];
}
else
{
return
m_HttpSessionSourceItemName;
}
}
}
}
/**/
///
<summary>
///
是否使用Session资源源
///
</summary>
public
static
bool
UserSessionSource
{
get
{
lock
(m_Locker)
{
return
Convert.ToBoolean(ConfigurationManager.AppSettings[
"
UserSessionSource
"
]);
}
}
}
#endregion
}
}
然后进行其他的一些封装操作
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:生成工厂类
*
*/
using
Index.Data.NHibernateSessionStorage.CFG;
using
NHibernate;
using
NHibernate.Cfg;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
用来生成ISession实例的工厂
///
</summary>
public
static
class
NHibernateDatabaseFactory
{
私有静态变量
#region
私有静态变量
private
static
object
m_Locker
=
new
object
();
private
static
Configuration m_Configuration
=
null
;
private
static
ISessionFactory m_SessionFactory
=
null
;
private
static
ISessionStorage m_Sessionsource;
#endregion
静态构造函数
#region
静态构造函数
static
NHibernateDatabaseFactory()
{
m_Sessionsource
=
ISessionStorageFactory.GetSessionStorage();
}
#endregion
内部静态变量
#region
内部静态变量
/**/
///
<summary>
///
NHibernate配置对象
///
</summary>
public
static
Configuration Configuration
{
get
{
lock
(m_Locker)
{
if
(m_Configuration
==
null
)
{
CreateConfiguration();
}
return
m_Configuration;
}
}
set
{ m_Configuration
=
value; }
}
/**/
///
<summary>
///
NHibernate的对象工厂
///
</summary>
internal
static
ISessionFactory SessionFactory
{
get
{
if
(
null
==
m_SessionFactory)
{
if
(m_Configuration
==
null
)
{
CreateConfiguration();
}
lock
(m_Locker)
{
m_SessionFactory
=
Configuration.BuildSessionFactory();
}
}
return
m_SessionFactory;
}
}
#endregion
公共方法
#region
公共方法
/**/
///
<summary>
///
建立ISessionFactory的实例
///
</summary>
///
<returns></returns>
public
static
ISession CreateSession()
{
if
(Config.UserSessionSource)
//
如果使用保存的ISession
{
ISession s
=
m_Sessionsource.Get();
if
(s
==
null
)
{
s
=
SessionFactory.OpenSession();
m_Sessionsource.Set(s);
}
return
s;
}
else
//
如果使用新ISession
{
return
SessionFactory.OpenSession();
}
}
#endregion
私有方法
#region
私有方法
private
static
void
CreateConfiguration()
{
m_Configuration
=
new
Configuration();
//
Add interceptor, if you need to.
//
_config.Interceptor = new Interceptor();
}
#endregion
}
}
使用方法
非Asp.net应用配置
<
appSettings
>
<
add
key
="SessionSourceType"
value
="threadStatic"
/>
<
add
key
="HttpSessionSourceItemName"
value
="NHSession"
/>
<
add
key
="UserSessionSource"
value
="true"
/>
</
appSettings
>
Asp.net应用配置
<
appSettings
>
<
add
key
="SessionSourceType"
value
="http"
/>
<
add
key
="HttpSessionSourceItemName"
value
="NHSession"
/>
<
add
key
="UserSessionSource"
value
="true"
/>
</
appSettings
>
<
httpModules
>
<
add
type
="Index.Data.NHibernateData.SessionStorage.NHSessionModule, Index.Data.NHibernate"
name
="NHSessionModule"
/>
</
httpModules
>
然后在程序开始的时候配置下
Index.Data.NHibernateData.SessionStorage.NHibernateFactory.Configuration.Configure(Server.MapPath(
"
~
"
)
+
"
\\hibernate.cfg.xml
"
);
对于Asp.net我会把次段代码写在Global.asax的Application_Start方法里。
posted on 2006-08-04 13:32
DDL
阅读(4095)
评论(14)
编辑
收藏
网摘
所属分类:
NHibernate
评论:
1373076
#1楼
2006-08-04 13:41 |
TerryLee
把你写的关于NHibernate的文章整理一下放在一篇文章里面做链接,并进行分类,这样可以收录到精华区:-)
回复
引用
查看
#2楼
[
楼主
] 2006-08-04 13:45 |
DDL
@TerryLee
我可能还会有十篇左右关于NHibernate的文章,等全部写完我会整理出一个目录,但这个过程可能会比较长,我尽量做到每周坚持一篇,所以暂时只能写一篇放一篇.
回复
引用
查看
#3楼
2006-08-04 15:47 |
TerryLee
@DDL
好的,支持!
回复
引用
查看
#4楼
2006-08-04 18:28 |
小新0574
写得不错,支持一下
回复
引用
查看
#5楼
2006-08-04 20:31 |
蔡克伦
支持!
另外在nh主页上有一个连接:
http://blogs.intesoft.net/simon/articles/16.aspx
">
http://blogs.intesoft.net/simon/articles/16.aspx
里面Simon Green也提供了一种做法,也是使用httpmodule来管理session(看来这已经成为了一种共识),我觉得更简洁一些,并且我把它用在实际项目中,运行良好。
回复
引用
查看
#6楼
2006-08-04 20:34 |
aspnetx
支持
学习中...
回复
引用
查看
#7楼
[
楼主
] 2006-08-07 10:07 |
DDL
@蔡克伦
http://blogs.intesoft.net/simon/articles/16.aspx
">
http://blogs.intesoft.net/simon/articles/16.aspx
里面的Session管理和在Asp.net中我写的其实是一样的,而我还考虑到了非Winfrom和其他的应用程序.
我单独把这块提出来,因为可以在他上面写数据访问的帮助类库.
回复
引用
查看
#8楼
2006-08-10 11:59 |
杨炎武
是不是这样使用了就不用再每次操作都不会再关系Session的关闭问题了?
而且我在使用的过程中发现一个问题,NHibernateDatabaseFactory.CreateSession()有时候获取到的Session是已经关闭了的,所以最好给它加上
if (!s.IsConnected)
s.Reconnect();
回复
引用
查看
#9楼
[
楼主
] 2006-08-10 15:44 |
DDL
@杨炎武
在我调用此类库的其他类库中,对此进行了其他的处理,所以我使用时不存在此问题.
至于你说的问题,你可以按你的想法进行更改.
回复
引用
查看
#10楼
2006-09-24 19:57 |
Zhongkeruanjian
Castle的NHibernateIntegration已经解决的这个问题,而且功能更加丰富。不过它依赖于IOC。如果不用IOC,还得改写。
回复
引用
查看
#11楼
2006-10-31 17:41 |
ivanking
@DDL
你的ThreadSessionSource 中的set()
if (value.IsConnected)
{
value.Disconnect();
}
为什么要把session断开连接再保存?
如果windows程序下,
我第一次在打开新session后需要保存而调用set
岂不是connection在不知情的情况下被断开?
ISession s = m_Sessionsource.Get();
if (s == null)
{
s = SessionFactory.OpenSession();
m_Sessionsource.Set(s);
}
这么做是否是出于别的考虑?
回复
引用
查看
#12楼
2007-03-26 17:21 |
茄子[未注册用户]
学习
回复
引用
#13楼
2008-05-03 18:15 |
ycguo[未注册用户]
对于有多个数据库连接的情况是不是不适用
回复
引用
#14楼
2008-11-18 09:12 |
幻蓝
--引用--------------------------------------------------
ivanking: @DDL
<br>你的ThreadSessionSource 中的set()
<br> if (value.IsConnected)
<br> {
<br> value.Disconnect();
<br> }
<br>为什么要把session断开连接再保存?
<br>如果windows程序下,
<br>我第一次在打开新session后需要保存而调用set
<br>岂不是connection在不知情的情况下被断开?
<br>
<br> ISession s = m_Sessionsource.Get();
<br> if (s == null)
<br> {
<br> s = SessionFactory.OpenSession();
<br>
<br> m_Sessionsource.Set(s);
<br> }
<br>这么做是否是出于别的考虑?
--------------------------------------------------------
他这样写的话,好处在于能控制数据库的链接资源。
在一个Session中多查询,多删除,处理时。可以只连一次,处理完后释放资源。
可见的资源管理,这样倒是很好。。。
不知道作者是不是这种意图。
回复
引用
查看
刷新评论列表
刷新页面
返回页首
发表评论
昵称:
[登录]
[注册]
主页:
邮箱:
(仅博主可见)
验证码:
看不清,换一个
评论内容:
登录
注册
[使用Ctrl+Enter键快速提交评论]
0
467688
jr5EXkWsZD8=
链接:
切换模板
导航:
网站首页
社区
新闻
博问
闪存
网摘
招聘
找找看
Google搜索
China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
China-Pub 计算机绝版图书按需印刷服务
历史上的今天:
2004-08-04
《.NET中统一的存储过程调用方法(收藏) 》的具体实现
相关文章:
最新IT新闻:
IBM发布全球首款开源智能编译器
IE颓势不减 微软下月公布最新浏览器架构
竞争日趋激烈 微软欲借 Windows 7 扭转战局
上海电信计划2012年80%用户实现100M带宽
数万名网友签名抗议星际争霸2取消局域网功能
相关链接:
只有偏执狂才能生存。
教堂尖项上的风标,即使由钢铁制成,如果不懂得顺应风势的艺术,一样会被暴风立即摧毁。
原创
技术文章,
转载
请注明来源。
<
2006年8月
>
日
一
二
三
四
五
六
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
与我联系
发短消息
搜索
常用链接
我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与
我的新闻
最新评论
我的标签
留言簿
给我留言
查看留言
我参加的小组
编程爱好者
我参与的团队
Design & Pattern团队(0/0)
上海.NET俱乐部(0/0)
广州.NET俱乐部(0/0)
南昌.net俱乐部(0/0)
O/R Mapping团队(0/0)
随笔分类
(83)
.NET(11)
Asp.net(5)
NHibernate(29)
Office编程(1)
XML
编程其他(1)
代码生成(4)
读书笔记(6)
规范文档(1)
设计(架构)模式(2)
思考和感悟(3)
随便写写(16)
团队管理(2)
正则表达式(2)
project
patterns & practices Application Architecture Guide
友情博客
eric_gqs
SHY520
Terrylee
林子
积分与排名
积分 - 234052
排名 - 186
最新随笔
1. 用我的MyGeneration模板生成NHibernate映射文件和关系(one-to-one,one-to-many,many-to-many)
2. 强大的代码生成工具MyGeneration
3. 请帮'Atlas'起个名字
4. NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析
5. 特里当选英格兰队新任队长
6. 发疯的live.com
7. NHibernate的Q&A(持续更新)
8. NHibernate的调试技巧和Log4Net配置
9. 建立OR Mapping团队的倡议
10. 诚邀博客链接
11. 推荐两款在线日程(任务)管理的站点
12. NHibernate的数据库连接机制分析和如何使用外部连接
13. NHibernate的Session管理
14. 有关NHibernate的问题请在此提出
15. [调查]如果你是个讲求编码规范的程序员,而碰到给变量、方法随意命名,注释又混乱的同事时你会怎么处理???
最新评论
1. re: NHibernate翻译文档提供下载(chm和html格式)
我也想要,能不能发到邮箱cgd_60802@sina.com
--cgd_60802
2. re: NHibernate的Q&A(持续更新)
@rooping 多个连接,多个配置文件就可以(*.hbm.xml),到时候判断一下读哪个就可以
--jcc
3. re: NHibernate快速起步
单元测试时出现如下错误 TestNHibernate.UserFixture.TestLoadUser: NHibernate.MappingException : No persister for:...
--eastcowboy
4. re: 有关NHibernate的问题请在此提出
楼主您好:我用的是one-to-many(双向),配置如下: <?xml version="1.0" encoding="utf-8" ?> <...
--piaowufeiyang_1
5. re: NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析
在使用tAddParentWithAddChild方法时,可以在
主表加进去,但是可以更新子表中有的字段,这个不太清楚了
希望能进行交流下~~~!
--piaowufeiyang_1
6. re: NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析
在one-to-many(双向)这里有一些疑问: 在使用tAddParentWithAddChild方法时,出现 Unexpected row count: 0; expected: 1的异常, 主表...
--piaowufeiyang_1
7. re: NHibernate快速起步
thanks!
--魔方网
8. re: NHibernate翻译文档提供下载(chm和html格式)
沙漠中看到绿洲!
--zhouyi292929
9. re: 用我的MyGeneration模板生成NHibernate映射文件和关系(one-to-one,one-to-many,many-to-many)
谁发一个DotNetScriptingEngine.dll到我邮箱matian516@sina.com,谢谢!
--matian516
10. re: NHibernate翻译文档提供下载(chm和html格式)
非常感谢,对初学者很实用
--stefanieforever
阅读排行榜
1. NHibernate翻译文档提供下载(chm和html格式)(24823)
2. 强大的代码生成工具MyGeneration(13732)
3. NHibernate快速起步(9948)
4. NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析(9647)
5. 用我的MyGeneration模板生成NHibernate映射文件和关系(one-to-one,one-to-many,many-to-many)(9308)
6. 自动代码生成器(6503)
7. NHibernate的调试技巧和Log4Net配置(5795)
8. NHibernate文档翻译完成(5790)
9. TreeView常用操作(5727)
10. 有关NHibernate的问题请在此提出(5688)
评论排行榜
1. NHibernate翻译文档提供下载(chm和html格式)(125)
2. 有关NHibernate的问题请在此提出(83)
3. 有追求的程序员是痛苦的吗?(76)
4. 用我的MyGeneration模板生成NHibernate映射文件和关系(one-to-one,one-to-many,many-to-many)(51)
5. NHibernate快速起步(38)
6. 自动代码生成器(31)
7. NHibernate的Q&A(持续更新)(27)
8. NHibernate文档翻译完成(25)
9. 强大的代码生成工具MyGeneration(24)
10. NHibernate的灵活配置(23)