现在的位置: 首页 > 综合 > 正文

Nhibernate 最佳实践

2013年02月23日 ⁄ 综合 ⁄ 共 2687字 ⁄ 字号 评论关闭

翻译的NHibernate参考文档

原英文页:http://nhforge.org/doc/nh/en/index.html#best-practices

 

一.     写细粒度的类并使用<component>映射

使用Address类封装street, suburb, state, postcode.

这种封装代码可重用和简化重构。

二.     在持久类中定义标识属性

NHibernate中的标识属性是可选的。出于各种原因,你都应该使用它。我们建议标识符应该是虚拟的('synthetic'),是应该没有任何事务意义的,并且是非原始类型。为了提供最大的弹性,使用Int64或 String.

三.     每个类用一个映射文件

不要用一个巨大的映射文件。用文件Eg/Foo.hbm.xml映射Eg.Foo类。在团队中,这样显著地利于理解。

四.     将映射文件嵌入程序集

映射文件和它对应的放在一起,并且在Visual Studio中将其声明为“嵌入的资源”。

五.     考虑外在化查询字符串

这是一个好的实践,如果你的查询是调用非ANSI标准的SQL函数。外在化查询字符串到映射文件可以使程序易于移植。

六.     使用参数

在ADO.NET中,总是将非常量替换为“?”。不要在查询中使用字符操作去绑定一个非常量值。更好的是在查询中考虑使用命名的参数。

七.     不要管理你的ADO.NET连接

Nhibernate让程序可以管理ADO.NET连接。但这被认为是最后的方法。如果你不能使用内置的连接提供器,可以考虑实现接口NHibernate.Connection.IconnectionProvider。

八.     考虑使用自定义类型

如果你有一个类型,可能来自于其它库,需要被持久化,但是没有必要作为component提供给访问器,你可以考虑实现NHibernate.UserTypes.IuserType。这种方法不用实现原代码到NHibernate类型的转换。

九.     在瓶颈处使用手工编写的ADO.NET

系统中非常需要高效率的地方,一些操作(如大规模更新/删除)可能直接用ADO.NET会更好一些。但是,请先等等你确定了解什么是瓶颈才决定。不要设想直接使用ADO.NET会更快。如果你要直接使用ADO.NET,打开一个NHibernate Isession来使用SQL语句的方法可能是值得的。这种方法你可以仍然使用相同的事务策略和它的连接提供器。

十. 理解ISession flushing

Isession会不时地与数据库同步它的持久状态。如果这种状态频繁发生将影响到执行效率。你有时可以通过取消自动flushing,甚至通过改变事务中查询和其他操作的顺序,来最小化不必要的flushing。

十一.  在三层体系结构中,考虑使用SaveOrUpdate()

当使用分布式架构,你应该传递中间层的持久对象到用户界面层。使用一个新session为每个请求服务。使用ISession.Update() 或 ISession.SaveOrUpdate()来持久对象状态。

十二.        两层架构中,考虑使用session disconnection

为了获取最好的性能,数据库事务不得不越短越好。然而,通常有必要执行一个长的程序事务,这种事务对于用户来说是一个单独的工作单元。这种程序事务可能跨越几个用户请求和相应周期。采用分离对象(Detached Objects)或简单地从ADO.NET断开NHibernate Session,然后在每个子序列请求中重连。不要在多于一个程序事务的用例中,使用单独的Session,否则,数据将受到破坏。

十三.        不要认为异常可被修复

与其说这条是“最佳”实践,不如说是必要实践。当异常发生时,ITransaction回滚, Isession 关闭。如果你不这样,NHibernate不能确保在内存中的状态就是持久化的状态. 在这种状态的特殊情况下,不要使用ISession.Load()来决定是否一个给定标识符的实例是否存在于数据库中。请使用Get()来查询。

十四.        倾向于使用lazy方式读取关系(associations)

谨慎地使用饥渴(outer-join)读取。对于大多没有在二级缓存中的类的关联,使用代理和/或lazy集合。对于缓存类的关联,它们具有高概率缓存,显示地设置fetch="select"对饥渴读取进行禁用。当对于一个特殊用例,outer-join读取是合适的,使用left join查询读取。

十五.        考虑从NHibernate中抽象你的事务逻辑

在接口后隐藏(NHibernate)数据存取代码。联合DAOThread Local Session模式。你甚至能够使用通过IuserType与NHibernate关联,通过手写ADO.NET持久化一些类(该建议是对于“足够大”的程序的,而不是对于只有五个表的)。

十六.        使用唯一的事务键实现Equals() 和 GetHashCode()

Implement Equals() andGetHashCode() using a unique business key.

如果你在Isession范围外比较对象,你必须实现Equals() 和 GetHashCode()。在Isession内,对象标识是可以保证的。如果你实现这些方法,不要使用数据库的标识符(If you implement these methods, never ever use the database identifier!)。一个瞬时对象并不具有标识符值,当该对象被保存时,NHibernate将指定一个值。如果该对象在Iset集合中被保存时,哈希数将改变,执行契约就会被打破。实现Equals()
和 GetHashCode()使用唯一的事务键,也就是,比较类属性唯一的联合。记住只有当该对象在Iset中,而不是所有生命周期,该键必须稳定并且唯一(不要像数据库主键一样稳定)。不要在Equals()中使用集合比较(lazy加载),并且要注意其它可能的相似类。

十七.        不要使用外来关系映射

Don't use exoticassociation mappings.

对于真正的多对多关系,好的用例很少。大多数时间,你需要额外的信息存储在关联表中。这种情况下,更好的做法是使用两个一对多关系到中间连接类。实际上,我们认为大多联系都是一对多和多对一的,当使用其他任何关联方式时,你应该小心对待,并问自己,这是否需要。

 

抱歉!评论已关闭.