登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP网盘
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
NHibernate延迟加载机制 - NHibernate 2.1.2
NHibernate延迟加载机制 - NHibernate 2.1.2
[ 复制链接 ]
佴莘莘
2025-5-29 15:08:46
动态代理的使用方法和相关概念可以参考Castle Dynamic Proxy
NHibernate实现延迟加载的主要结构:
BuildSessionFactory的时候:
1. 根据proxyfactory.factory_class的配置创建IProxyFactoryFactory对象
2. 如果use_proxy_validator配置为true(默认为true),加载实体映射元数据之后,对需要代理的实体使用IProxyFactoryFactory的ProxyValidator进行验证(例如要求实体有默认构造器、方法属性必须为virtual类型等)
3. 为需要代理的实体类型创建IProxyFactory,并调用IProxyFactory对象的PostInstantiate方法
对每一个需要代理的实体类型都会创建一个IProxyFactory对象并缓存,创建代理对象则通过IProxyFactory的GetProxy方法完成
AbstractProxyFactory主要是实现PostInstantiate方法,这个方法主要是将创建代理对象所需的信息记录下来,例如EntityName(字符串的实体类名)、PersistentClass(代理对象的System.Type)、Interfaces(代理对象需要额外实现的接口,例如INHibernateProxy),其他几个记录的属性则为单主键和组合主键id的get、set方法
ProxyFactory则主要实现GetProxy方法,使用Castle或者LinFu等动态代理库以及上述信息创建代理对象
创建代理对象:
IProxyFactory.GetProxy方法完成
1. 创建一个LazyInitializer对象。LazyInitializer实现了各个动态代理类库的拦截器接口
2. 通过Castle、LinFu、Spring等动态代理库创建class proxy或者interface proxy的代理对象
创建代理对象时INHibernateProxy作为一个mixin的接口,NHibernate内部用这个接口来区分代理对象和真实对象。对这个接口的方法调用则在拦截器中处理
延迟加载:
创建代理对象时,均使用NHibernate.ByteCode.LinFu或者NHibernate.ByteCode.Castle中的LazyInitializer类作为拦截器,因此对代理对象的方法调用都在LazyInitializer中拦截处理
ILazyInitializer接口主要用于延迟加载的相关处理
首先,对代理对象某些方法的调用不会触发延迟加载行为,比如读取主键的值、组合类型属性的主键值、没有override的情况下调用Object基类的一些方法以及Dispose方法等,这些逻辑在BasicLazyInitializer的Invoke方法中处理
当调用代理对象的其他方法时,触发延迟加载行为。加载处理在AbstractLazyInitializer的Initialize方法中完成,加载实体所需要的信息(主要有session、id、实体的类型)在创建LazyInitializer对象时均已经提供,加载过程仍然使用一级缓存、二级缓存、数据库这样一个加载顺序
加载的实体对象与代理对象是两个独立的对象,NHibernate并没有将加载后的实体属性值设置到代理对象上,估计一是考虑到有interface proxy存在的情况,另外实际加载过程是比较独立的,他会重新创建一个真实的实体对象,会放入一级、二级缓存中,还有一点,这种处理方式NHibernate以及client都可以通过代理对象来得到加载后的真实对象。真实的实体对象保存在AbstractLazyInitializer的Target属性中,完成加载以后,拦截器中通过反射来调用target对象的方法
下面代码示例怎么由代理对象得到真实对象(非NHibernate官方公布的方法,慎用):
ISessionFactory sf = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sf.OpenSession())
{
//仅创建代理对象,没有实际加载
MyUser proxy = session.Load<MyUser>(11);
Console.WriteLine(proxy.GetType().FullName);
//因为override了ToString方法,因此下面这个调用将触发加载行为
Console.WriteLine(proxy.ToString());
//获取真实对象
NHibernate.Proxy.INHibernateProxy nhProxy = proxy as INHibernateProxy;
MyUser real = nhProxy.HibernateLazyInitializer.GetImplementation() as MyUser;
Console.WriteLine(real.GetType().FullName);
Console.WriteLine(real.ToString());
}
sf.Close();
Console.ReadKey();
复制代码
下面是运行结果:
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
安全
签约作者
程序园优秀签约作者
发帖
佴莘莘
2025-5-29 15:08:46
关注
0
粉丝关注
22
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9986
凶契帽
9990
处匈跑
9990
4
黎瑞芝
9990
5
杭环
9988
6
猷咎
9988
7
鲫疹
9988
8
接快背
9988
9
里豳朝
9988
10
氛疵
9988
查看更多