NHibernate使用点滴

 工作需要使用NHibernate,用于比较庞大的关系模型。以下是使用过程中遇到问题的汇总(不断更新中)。

1. 近日遇到"persistence context reported no row snapshot for (某个entity)"问题,通过反复分析,发现其原因是对应entity有一个以one-to-many联系之的owner没有保存(map和persist)。而且这个owner是从一个abstract class继承下来,这个class被标记了persist并被我做的拾取器收到并保存,而这个entity对应的类(扩展了这个abstract class)没有保存到数据库(尽管在这个例子中,扩展类没有任何额外数据成员,但在关系数据库模型中也没有它的位置标识,就像在面向对象模型中也没了相应的位置),由此发生了悬空的引用,因此出现了这个问题(虽然错误提示信息很难联想到这个问题,而且搜索网上可以发现结果多数为NHibernate源代码页,而且看这些源代码耗时很大,帮助也不太大)。

2. NHibernate产生Schema的功能很强大好用,但一个问题是它把所有可能的依赖关系都加到关系数据库中成为约束(constraints),而在具体数据库访问中,OO侧的流程或NHibernate本身的操作都无法保证在能满足这个约束在数据创建过程中都得到满足,尤其对于比较复杂的关系模型。因此一般尤其在实验阶段最好约束全部去除(如果业务规则不需要数据库维护这种关系约束,那就尽量不用),最简单的是用Stored Procedure,这可以在网上搜索到示例代码,比较方便。(后发现,通常只要OO测基本保证对象关系的正确性和一致性,这个约束是能够被遵守的)

3. OO侧代码产生的Id尽量保证为正数,零Id很不好,容易发生冲突(零Id相当于null)。

4. 一般如果关闭Cascade的时候(初创阶段,为了方便或效率考虑),保存和更新要由OO侧对相应entity实例定点实施。

5. List方式one-to-many映射不允许Reverse,即始终由one侧负责读取(主要原因可能是index的存在)。

6. 能用Reverse尽量用Reverse,让many侧负责读取操作,这样能从优化SQL生成减少SQL发送数量角度提高效率(需要EagerLoading)。(详情待整理)

7. 关于LazyLoading,对于many-to-one,可以在lazy-load属性或Fluent的LazyLoad()方法上采用noproxy参数,使得NHibernate不产生proxy以作为局部加载的多态对象。但这往往有副作用,会导致运行异常(估计可能是proxy被null取代),有一定的使用注意事项。

8. 对一个模型关闭Session后再以打开一个新的Session并联入,Custom Collections会遇到问题,对于one-to-many映射中的线性Custom Collection可能问题不大(机制尚不明了,可能与Reference的存在有关),但one-to-many中用于查询的Dictionary Mapping肯定会出问题,因为这个映射用的是一个单独表。跨Session之后,Custom Collections仍然用的一起建立的Proxies,可能Session相关设施都无法更新,这样在新的Session中这个表无法得到正确存储。尝试手动将这些Dictionaries在OO侧Unproxy能是问题暂时消除。(详情待整理或以另行撰文探讨)

(待进一步更新)

你可能感兴趣的:(Hibernate)