nhibernate 持久化GetCurrentSession 设置load 不持久化

帮助企业打造成功软件!
热门搜索:
NHibernate.Search 基于Lucene.NET的全文索引
NHibernate.Search 基于Lucene.NET的全文索引
| 作者:慧都控件网 |
09:38:12| 阅读 0次
概述:NHibernate.Search现在是NHiberante Contrilb下面的一个还没有发布的项目,也是从Hibernate.Search移植而来,把NHibernate和Lucene.NET结合在一起,ORM持久化对象到数据库中,Lucene.NET提供索引及查询支持.
NHibernate.Search现在是NHiberante Contrilb下面的一个还没有发布的项目,也是从Hibernate.Search移植而来,把NHibernate和Lucene.NET结合在一起,ORM持久化对象到数据库中,Lucene.NET提供索引及查询支持.
&&&& 下面在实际使用一下NHibernate.Search的使用:
&&&& 由于这个项目还没有发布,它的很多特性也是一直在变化,所以现在只是以我下载的版本为准,如果你想尝试此项目,请下载最下面的代码,里面包括自己编译生成的NHibernate.Search及最新的Lucene.net相关的dll.
&&& 1.修改你的NHibernate配置信息的地方,同样添加NHibernate.Search的配置信息.
&configSections&
&section name=&hibernate-configuration& type=&NHibernate.Cfg.ConfigurationSectionHandler, NHibernate&/&
&section name=&nhs-configuration& type=&NHibernate.Search.Cfg.ConfigurationSectionHandler, NHibernate.Search& requirePermission=&false& /&
&sectionGroup name=&system.web.extensions& type=&System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF&&
&/configSections&&&&&&&& 需要注意的是,在NHibernate.Search之前的版本中,曾经NHibernate.Search的配置信息和NHIbernate的放在一起.接下来,我们来看下具体的配置块:
&&hibernate-configuration xmlns=&urn:nhibernate-configuration-2.2&&
&&&&&&& &bytecode-provider type=&lcg&/&
&&&&&&& &reflection-optimizer use=&true&/&
&&&&&&& &session-factory name=&NHibernateSearch.Demo&&
&&&&&&&&&&& &property name=&connection.provider&&NHibernate.Connection.DriverConnectionProvider, NHibernate&/property&
&&&&&&&&&&& &property name=&connection.connection_string&&
&&&&&&&&&&&&&&& Data Source=|DataDirectory|Demo.db3;Version=3;Compress=Fsynchronous=OFF
&&&&&&&&&&& &/property&
&&&&&&&&&&& &property name=&show_sql&&true&/property&
&&&&&&&&&&& &property name=&dialect&&NHibernate.Dialect.SQLiteDialect&/property&
&&&&&&&&&&& &property name=&connection.driver_class&&NHibernate.Driver.SQLite20Driver&/property&
&&&&&&&&&&& &property name=&prepare_sql&&true&/property&
&&&&&&&&&&& &property name=&cache.provider_class&&NHibernate.Cache.HashtableCacheProvider, NHibernate&/property&
&&&&&&&&&&& &property name=&cache.use_query_cache&&true&/property&
&&&&&&&&&&& &mapping assembly=&NHibernateSearch.Demo.Model&/&
&&&&&&& &/session-factory&
&&& &/hibernate-configuration&
&&nhs-configuration xmlns='urn:nhs-configuration-1.0'&
&&&&&&& &search-factory& sessionFactoryName=&NHibernateSearch.Demo&&
&&&&&&&&&&& &property name='hibernate.search.default.directory_provider'&NHibernate.Search.Store.
FSDirectoryProvider, NHibernate.Search&/property&
&&&&&&&&&&& &property name='hibernate.search.default.indexBase'&~/Index&/property&
&&&&&&&&&&& &property name='hibernate.search.default.indexBase.create'&true&/property&
&&&&&&& &/search-factory&
&&& &/nhs-configuration&&&&& 上面的是NHibernate的配置信息,由于我在示例程序中使用的是SQLite数据库,所以这个Demo也是一个SQLite+NHibernate的案例,而且里注意SQLite的连接字符串Data Source=|DataDirectory|Demo.db3,这样的话,只要把数据文件放在App_Data下面就可以运行了,而不用再去填写数据库文件的绝对路径.
&&&& 下面是NHibernate.Search的配置,我们采用基于文件目录的全文检索,索引文件放在根目录下面的Index文件夹下面.
&&&& 另外,我们设置一下NHibernate的事件监听(如果不我们设置的话,我们要手动去调用,才能够使NHibernate在持久化对象时,同时处理全文索引),现在这个事件配置还不支持直接在NHibernate这样配置:
&&&&&&&& &listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-insert'/&
&&&&&&&& &listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-update'/&
&&&&&&& &listener class='NHibernate.Search.Event.FullTextIndexEventListener, NHibernate.Search' type='post-delete'/&
&&&&& 现在我们只能在创建SessionFactory前,手动添加这个配置信息:
&&&&&&&&&&&&&& Configuration configuration = new Configuration();
&&&&&&&&&&&&&&& configuration.SetListener(NHibernate.Event.ListenerType.PostUpdate, new FullTextIndexEventListener());
&&&&&&&&&&&&&&& configuration.SetListener(NHibernate.Event.ListenerType.PostInsert, new FullTextIndexEventListener());
&&&&&&&&&&&&&&& configuration.SetListener(NHibernate.Event.ListenerType.PostDelete, new FullTextIndexEventListener());
&&&&&&&&&&&&&&& configuration.Configure();
&&&&&&&&&&&&&&& sessionFactory=& configuration.BuildSessionFactory();&&&&& 我们为更新,删除,添加都配置了全文索引的事件监听,这样就能够保证索引文件里的数据和实际数据库里的保持一致,不要担心,这的性能也有考虑,这里可以支持最大提交数量,而不一定非要每条操作都去更改索引文件.
&&&&& 首先我们要在NHibernate实体对象这里添加一些NHibernate.Search的一些关于全文索引的属性声明.不知道这里以后会不会支持xml的配置而不是修改原来的对象代码.
&&& [Indexed(Index = &Book&)]
&&& public class Book
&&&&&&& [DocumentId]
&&&&&&& public& virtual string BookID
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&& [Field(Index.Tokenized, Store = Store.Yes)]
&&&&&&& public virtual string Title
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&& [Field(Index.Tokenized, Store = Store.Yes)]
&&&&&&& public virtual string Authors
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&& [Field(Index.Tokenized, Store = Store.Yes)]
&&&&&&& public virtual string Publisher
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&& [Field(Index.Tokenized, Store = Store.Yes)]
&&&&&&& public virtual string Summary
&&&&&&&&&&&
&&&&&&&&&&&
&&& }&&&& 用过Lucene.Net的朋友们可能会发现,其实这些标识,原来在不使用NHibernate时是直接针对字段的.而现在只是针对一个业务对象的属性.这样的话,但数据添加或者更改时,就会自动的进行索引,但数据进行删除时,也自动更新索引,而可以不进行人为的干预.
&&& 上面是一个对象Book,其中包含名称,作者,出版社,简介.我们要想实现对这几个属性进行全文检索的话,以前只能够同时拼几个LiKE,如果针对数据库,数据库数据的话肯定性能不会好,但是如果针对索引文件就不一样了.首先我们看一下怎么来实现搜索:
public&& static IList&BookSearchResult&& FindBooks(string query)
&&&&&&&&&&& IList&BookSearchResult& results = new List&BookSearchResult&();
&&&&&&&&&&& Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer();
&& MultiFieldQueryParser parser = new MultiFieldQueryParser(new string[] { &Title&, &Summary&, &Authors&, &Publisher&&&& },&&&&&&&& analyzer);
&&&&&&&&&&& Query queryO
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& queryObj = parser.Parse(query);
&&&&&&&&&&& }
&&&&&&&&&&& catch (ParseException)
&&&&&&&&&&& {
&&&&&&&&&&&&&&&
&&&&&&&&&&& }
&&&&&&&&&&& IFullTextSession session = Search.CreateFullTextSession(NHibernateHelper.GetCurrentSession());
&&&&&&&&&&&&&&&&&&&&&&& ///1
&&&&&&&&&&& System.Type targetType = typeof(Book);
&&&&&&&&&&& IQuery nhQuery = session.CreateFullTextQuery(queryObj, new Type[] { targetType });
&&&&&&&&&&& IList&Book& books = nhQuery.List&Book&();
&&&&&&&&&&& NHibernate.Cfg.Configuration& cf =& new Configuration().Configure();
&&&&&&&&&&& SearchFactoryImpl searchFactory&& = SearchFactoryImpl.GetSearchFactory(cf);
&&&&&&&&&&& IDirectoryProvider provider = searchFactory.GetDirectoryProviders(targetType)[0];
&&&&&&&&&&& Workspace workspace = new Workspace(searchFactory);
&&&&&&&&&&& IndexReader indexReader = workspace.GetIndexReader(provider, targetType);
&&&&&&&&&&& Query simplifiedQuery = queryObj.Rewrite(indexReader);
&&&&&&&&&&& SimpleHTMLFormatter formatter = new SimpleHTMLFormatter(&&b class='term'&&, &&/b&&);
&&&&&&&&&&& Highlighter hTitle = GetHighlighter(simplifiedQuery, formatter, &Title&, 100);
&&&&&&&&&&& Highlighter hSummary = GetHighlighter(simplifiedQuery, formatter, &Summary&, 200);
&&&&&&&&&&& Highlighter hAuthors = GetHighlighter(simplifiedQuery, formatter, &Authors&, 100);
&&&&&&&&&&& Highlighter hPublisher = GetHighlighter(simplifiedQuery, formatter, &Publisher&, 100);
&&&&&&&&&&& foreach (Book book in books)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& BookSearchResult result = new BookSearchResult(book);
&&&&&&&&&&&&&&& TokenStream tsTitle = analyzer.TokenStream(&Title&, new System.IO.StringReader(book.Title ?? string.Empty));
&&&&&&&&&&&&&&& result.HighlightedTitle = hTitle.GetBestFragment(tsTitle, book.Title);
TokenStream tsAuthors = analyzer.TokenStream(&Authors&, new System.IO.StringReader(book.Authors ?? string.Empty));
&&&&&&&&&&&&&&& result.HighlightedAuthors = hAuthors.GetBestFragment(tsAuthors, book.Authors);
&TokenStream tsPublisher = analyzer.TokenStream(&Publisher&, new System.IO.StringReader(book.Publisher ??&&&&&&&&&&&&&&& string.Empty));
&&&&&&&&&&&&&&& result.HighlightedPublisher = hPublisher.GetBestFragment(tsPublisher, book.Publisher);
TokenStream tsSummary = analyzer.TokenStream(&Summary&, new System.IO.StringReader(book.Summary ?? string.Empty));
result.HighlightedSummary = hSummary.GetBestFragments(tsSummary, book.Summary, 3, & ... &br /&&br /& ... &);
&&&&&&&&&&&&&&& results.Add(result);
&&&&&&&&&&& }
&&&&&&&&&&&
&&&&&&& }&&&&& 相信使用过Lucene.Net的朋友对上面的代码并不难理解,所有使用IFullTextSession的操作,都会进行全文索引的处理.另外这里还有多字段解析和分词的技术,就不详细介绍了.上面还使用了对查询关键字进行高亮显示,其中的BookSearchResult实体也只是对Book进行了包装,进行了显示的一些处理.具体请查看源代码.
&&&&& 你可以在上面注释的///1处,添加对Book的一些操作,就可以显示的查看索引文件是否也同时进行了更新了.
&&&& 下载直接运行整个项目,输入&程序&关键字,你会发现,在很短时间内,列出来了符合的记录,并黑色显示匹配的字(至于与不进行索引的搜索性能对比,留给以后再做吧):
慧都控件|提供软件技术整体解决方案
云集全球三千余款优秀控件、软件产品,提供行业领先的咨询、培训与开发服务
企业QQ:|电话:023-
服务与支持
重庆 / 023-
北京 / 010-
400-700-1020
慧都旗下网站
慧都科技有限公司 版权所有 Copyright
100%正版软件
400-700-1020
<input type="hidden" id="url" value=""/>Nhibernate GetCurrentSession() Throw an exception...........【西安石油大学吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:140,703贴子:
Nhibernate GetCurrentSession() Throw an exception...........收藏
ibernate GetCurrentSession() Throw an exception: No session bound to the current context?why???????
美国大学 石油工程天道留学直击美国留学院校就读 2017留学360度申请倾情曝光 先人一步了解2017美国大学 石油工程申请详情.天道留学服务机构,为您合理规划 步步为营.好留..
楼主外语系的?
suibuzhidanjueli!
自动发贴软件。发错地方了
登录百度帐号推荐应用NHibernate学习
我的图书馆
NHibernate学习
  内容摘要
    NHibernate简介
    ORM简介      NHibernate优缺点
  一、NHibernate简介
  什么是?NHibernate?NHibernate是一个面向.NET环境的对象/关系数据库映射工具。对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。
  在今日的企业环境中,把面向对象的软件和关系数据库一起使用可能是相当麻烦和浪费时间的。而NHibernate不仅仅管理.NET类到数据库表的映射(包括.NET 数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和ADO.NET处理数据的时间。
  NHibernate的目标主要是用于与数据持久化相关的编程任务,能够使开发人员从原来枯燥的SQL语句的编写中解放出来,解放出来的精力可以让开发人员投入到业务逻辑的实现上。对于以数据为中心的程序,开发人员往往是在数据库中使用存储过程来实现商业逻辑,这种情况下NHibernate可能不是最好的解决方案,但对于那些基于.NET,并且能够实现OO业务模型和商业逻辑的中间层应用,NHibernate是最有用的。NHibernate可以帮助用户消除或者包装那些针对特定厂商的SQL代码,并且帮用户把结果集从表格式的表示形式转换成一系列的对象。   
  NHibernate是一个目前应用的最广泛的开放源代码的对象关系映射框架,它对Java的JDBC(类似于ADO.Net)进行了非常轻量级的对象封装,使得程序员可以随心所欲的使用对象编程思维来操纵数据库,目前在国内Java开发界已经颇为流行,Hibernate+Spring往往是很多Java公司招聘的要求。而NHibernate,顾名思义,如同NUnit,NAnt一样,是基于.Net的Hibernate实现,但是目前介绍NHibernate的资料非常少,缺少一个系统完整的教程来全面的展现和深入NHibernate,而且现在NHibernate的文档又残缺不全,少的可怜,很多NHibernate的学习者往往都是通过Hibernate的文档来学习,但是毕竟不是所有的.Net开发者都熟悉Java,也不是所有的人都有精力有时间去学习Java,所以,我准备开始一个Step by Step的NHibernate教程,以便有兴趣的朋友能够快速的熟悉NHibernate,能够更快地体验NHibernate的开发乐趣。   
  NHibernate 是一个基于.Net 的针对关系型数据库的对象持久化类库。NHibernate 来源于非常优秀的基于Java的Hibernate 关系型持久化工具。   
  NHibernate 从数据库底层来持久化你的.Net 对象到关系型数据库。NHibernate 为你处理这些,远胜于你不得不写SQL去从数据库存取对象。你的代码仅仅和对象关联,NHibernat 自动产生SQL语句,并确保对象提交到正确的表和字段中去。
  二、ORM简介
  什么是ORM?对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。   
  面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。   
  让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
  如果打开你最近的程序(如,PetShop4.0),看看DAL(数据库访问层)代码,你肯定会看到很多近似的通用的模式。我们以保存对象的方法为例,你传入一个对象,为SqlCommand对象添加SqlParameter,把所有属性和对象对应,设置SqlCommand的CommandText属性为存储过程,然后运行SqlCommand。对于每个对象都要重复的写这些代码。除此之外,还有更好的办法吗?有,引入一个O/R Mapping。实质上,一个O/R Mapping会为你生成DAL。与其自己写DAL代码,不如用O/R Mapping。你用O/R Mapping保存,删除,读取对象,O/R Mapping负责生成SQL,你只需要关心对象就好。
  三、NHiberante的优缺点
  3.1 优点
  (1).面向对象:NHiberante的使用时只需要操纵对象,使开发更对象化,抛弃了数据库中心的思想,完全的面向对象思想。
  (2).透明持久化:带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。这些对象可能是普通的POCO,这个对象没有实现第三方框架或者接口,唯一特殊的是他们正与(仅仅一个)Session相关联。一旦这个Session被关闭,这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用。(例如,用作跟表示层打交道的数据传输对象。)
  (3).它没有侵入性,即所谓的轻量级框架。正因为它具有透明持久化的优点,它才没有侵入性,才是一个轻量级框架。恒定一个框架为重量级、还是轻量级,是根据其侵入性而定夺的。而NHibernate就是一个轻量级ORM框架。
  (4).较好的移植性:支持多种数据库,便于数据库的迁移。
  (5).缓存机制:提供一、二级缓存和查询缓存。
  (6).开发效率:众所周知,使用NHibernate可以简化程序开发,从而达到快速开发的目的。作为软件公司,项目管理的关键就是控制开发成本。正因为使用NHibernate后所写的代码量减少了,相对于原先使用“SqlHelper、DAL、BLL”开发程序的项目周期缩短了,成本就降低了。
  3.2 缺点
  (1).内存消耗:直接使用“SqlHelper、DAL、BLL”无疑是最省内存的。使用NHibernate后,内存开销比较大,这点是毋庸置疑的。
  (2).批量数据库的处理:由于NHibernate是基于面向对象的ORM框架,处理数据库的方式是针对单个对象的。对数据库的增、删、改都是正对一条记录而言。对于批量修改、删除数据,不适合用NHiberante。这也是所有OR框架弱点,其原因,我认为是在于与缓存机制的冲突。
  (3).较多使用数据库特性时,也不适合使用NHiberante。如数据库中大量的存储过程、触发器、特点的SQL语句。
  (4).表关系比较混乱时也不适合使用NHiberante。NHibernate只适合于表与表的关系比较明确的环境中。如本应该建立外键的,没有建立外键。这时使用NHiberante不仅没有减少工作量,反而增加了工作量。
  (5).学习成本:相对于NHibernate来说,使用“SqlHelper、DAL、BLL”操作数据库,学习成本比较低,而且上手很快。使用NHibernate需要有一定OOP(面向对象编程)和OOD(面向对象设计)的基础,这对于基础薄弱的程序员来说,从面向过程的编程到面向对象的编程,需要一定的投入;一般情况下需要学习1个月左右的时间才能够深入NHiberante。
  文章出处:
  内容摘要
    NHibernate的开发环境
    NHibernate的结构体系      NHibernate的配置
  一、NHibernate的开发环境
  NHibernate的英文官方网站为:
  NHibernate目前最新的版本是3.0.0.GA,其下载地址是:
  我可以下载NHibernate-3.0.0.GA-bin.zip(编译后的dll),也可以下载&NHibernate-3.0.0.GA-src.zip(源文件),另外再下载NHCH-3.0.0.GA-bin.zip(NHibernate二级缓存库)。
  下载并解压NHibernate-3.0.0.GA-bin.zip后,如图1.1所示。
其中名为“Required_Bins”的文件夹所放置的是NHiberante主程序的dll程序集。
    (1).Antlr3.Runtime.dll为:Antlr的程序集。Antlr(ANother Tool for Language Recognition)是一个工具,它为我们构造自己的识别器(recognizers)、编译器(compiler)和转换器(translators)提供了一个基础。通过定义自己的语言规则,Antlr可以为我们生成相应的语言解析器,这样便可以省却了自己全手工打造的劳苦。
    (2).Iesi.Collections.dll为:NHibernate程序的集合库,因为在.NET4.0之前,没有提供ISet这样的集合,所以NHiberante框架的设计者们就将ISet这样的集合放置在这个程序集里。我建议NHiberante框架的设计人员,在.NET4.0以后的程序,使用System.Collections.Generic.ISet&T&这个接口。
    (3).NHibernate.dll为主程序集
    (4).Remotion.Data.Linq.dll为:NHibernate to Linq的类库。
    (5).nhibernate-configuration.xsd和nhibernate-mapping.xsd分别为NHibernate程序配置和映射配置的xsd文件,我们把这个两个文件复制到Microsoft Visual Studio安装目录的\Xml\Schemas下,就会有xml的自动提示功能。
名为“Required_For_LazyLoading”的文件夹所放置的是NHiberante延迟加载代理用到的程序集,其中提供了Castle、LinFu、Spring这三种代理类。我选择其中一项就可以了。
名为“Configuration_Templates”的文件夹所放置的是NHiberante的配置模板。已给出了FireBird、MSSQL、MySql、Oracle、PostgreSQL、SQLite的配置模板。
  二、NHiberante的结构体系(Architecture)
  从图2.1可以看出,NHibernate使用数据库和配置信息来为应用程序提供持久化服务(以及持久的对象)。
  我们来更详细地看一下NHibernate运行时体系结构。由于NHibernate非常灵活,且支持多种应用方案, 所以我们这只描述一下两种极端的情况。“轻型”的体系结构方案,要求应用程序提供自己的ADO.NET 连接并管理自己的事务。这种方案使用了NHibernate API的最小子集:
    图2.2
  “全面解决”的体系结构方案,将应用层从底层的ADO.NET API中抽象出来,而让NHibernate来处理这些细节。
  图2.3中各个对象的定义如下:
ISessionFactory (NHibernate.ISessionFactory)
针对单个数据库映射关系经过编译后的内存镜像,是线程安全的(不可变)。 它是生成ISession的工厂,本身要用到IConnectionProvider。 该对象可以在进程或集群的级别上,为那些事务之间可以重用的数据提供可选的二级缓存。
ISession (NHibernate.ISession)
表示应用程序与持久储存层之间交互操作的一个单线程对象,此对象生存期很短。 其隐藏了ADO.NET连接,也是 ITransaction的工厂。 其会持有一个针对持久化对象的必选(第一级)缓存, 在遍历对象图或者根据持久化标识查找对象时会用到。
持久的对象及其集合(Persistent Objects and Collections)
带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。 这些对象可能是普通的POCOs, 唯一特殊的是他们正与(仅仅一个)ISession相关联。 一旦这个ISession被关闭, 这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用。 (例如,用作跟表示层打交道的数据传输对象。)
瞬态(transient)和脱管(detached)的对象及其集合
那些目前没有与ISession关联的持久化类实例。 他们可能是在被应用程序实例化后, 尚未进行持久化的对象。 也可能是因为实例化他们的ISession已经被关闭而脱离持久化的对象。
ITransaction (NHibernate.ITransaction)
(可选的)应用程序用来指定原子操作单元范围的对象,它是单线程的,生命周期很短。 它通过抽象将应用从底层具体的ADO.NET事务隔离开。 某些情况下,一个ISession之内可能包含多个ITransaction对象。
IConnectionProvider (NHibernate.Connection.IConnectionProvider)
(可选的)生成ADO.NET连接以及Command对象的工厂。 它通过抽象将应用从底层的IDbConnection或IDbCommand隔离开。 仅供开发者扩展/实现用,并不暴露给应用程序使用。
IDriver (NHibernate.Driver.IDriver)
(可选的)一个封装了不同ADO.NET providers之间的差异(利用参数命名转换等ADO.NET支持的特性)的接口。
ITransactionFactory (NHibernate.Transaction.ITransactionFactory)
(可选的)生成ITransaction对象实例的工厂。 仅供开发者扩展/实现用,并不暴露给应用程序使用。
  三、NHibernate的配置
  由于NHibernate是为了能在各种不同环境下工作而设计的, 因此存在着大量的配置参数. 幸运的是多数配置参数都有比较直观的默认值。我打开MSSQL.cfg文件,如图所示,可以观察到NHibernate的配置。
3.1 NHibernate提供ADO.NET连接配置
connection.provider_class
实现IConnectionProvider接口的类型。
例如: (如果是NHibernate内部的IConnectionProvider实现类)full.classname.of.ConnectionProvider,
(如果是自定义的NHibernate外部的IConnectionProvider实现类 )full.classname.of.ConnectionProvider, assembly。
connection.driver_class
如果使用DriverConnectionProvider,实现IDriver接口的类型。
(如果是NHibernate内部的实现的IDriver类型)full.classname.of.Driver
(如果是自定义的NHibernate外部的IDriver实现类 )full.classname.of.Driver, assembly。
这个配置通常是不需要配置的,如果设置好了hibernate.dialect一般会自动选好对应的IDriver。 详细的dialect与IDriver的默认对应关系可以查看API文档。
connection.connection_string
数据库连接字符串
connection.connection_string_name
数据库连接字符串名称(定义在.Net配置文件&connectionStrings&配置节里面的连接字符串名。
connection.isolation
ADO.NET事务隔离级别, 查看System.Data.IsolationLevel类来了解各个值的具体意义, 但请注意多数数据库都不支持所有的隔离级别。
例如: Chaos, ReadCommitted, ReadUncommitted, RepeatableRead, Serializable, Unspecified
connection.release_mode
指定ADO.NET何时释放数据库连接。
例如: auto (默认) | on_close | after_transaction
注意,这些设置仅对通过ISessionFactory.OpenSession得到的ISession起作用。
对于通过ISessionFactory.GetCurrentSession得到的ISession,
所配置的ICurrentSessionContext实现控制这些ISession的连接释放模式。
command_timeout
指定NHibernate生成的IDbCommands对象的超时时间。 .
adonet.batch_size
指定用ADO.Net的批量更新的数量,默认设置为0(不启用该功能)。
proxyfactory.factory_class
代理工厂配置。用于指定是哪个中间件提供的延迟加载代理
3.2 可选的配置属性
有大量属性能用来控制NHibernate在运行期的行为. 它们都是可选的, 并拥有适当的默认值。
设置NHibernate的Dialect类名 - 允许NHibernate针对特定的关系数据库生成优化的SQL
可用值: full.classname.of.Dialect, assembly
default_schema
在生成的SQL中, 将给定的schema/tablespace附加于非全限定名的表名上。
可用值: SCHEMA_NAME
use_outer_join
允许外连接抓取,已弃用,请使用max_fetch_depth。
可用值: true | false
max_fetch_depth
为单向关联(一对一, 多对一)的外连接抓取(outer join fetch)树设置最大深度。
值为0意味着将关闭默认的外连接抓取
可用值:建议在0 到3之间取值。
use_reflection_optimizer
开启运行时代码动态生成来替代运行时反射机制(系统级属性)。
&使用这种方式的话程序在启动会耗费一定的性能,但是在程序运行期性能会有更好的提升。
注意即使关闭这个优化, Hibernate还是需要CGLIB. 你不能在hibernate.cfg.xml中设置此属性。
这个属性不能在hibernate.cfg.xml或者是应用程序配置文件&hibernate-configuration& 配置节中设置。&
可用值: true | false
bytecode.provider
指定字节码provider用于优化NHibernate反射性能。 null代表完全关闭性能优化,
lcg用于轻量级的代码动态生成,codedom基于CodeDOM代码动态生成。
可用值: null | lcg | codedom
cache.provider_class
设置缓存实现类(实现ICacheProvider接口的类)
可用值: classname.of.CacheProvider, assembly
cache.use_minimal_puts
以频繁的读操作为代价, 优化二级缓存来最小化写操作(对群集缓存有效)。
可用值: true | false
cache.use_query_cache
允许查询缓存, 个别查询仍然需要被设置为可缓存的.
可用值: true | false
cache.query_cache_factory
自定义实现IQueryCacheFactory接口的类名, 默认为内建的StandardQueryCacheFactory。
可用值: classname.of.QueryCacheFactory, assembly
cache.region_prefix
二级缓存区域名的前缀。
可用值: prefix
query.substitutions
将NHibernate查询中的符号映射到SQL查询中的符号 (符号可能是函数名或常量名字)。
可用值: hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
query.substitutions true=1, false=0 将导致符号true和false在生成的SQL中被翻译成整数常量
输出所有SQL语句到控制台.
可用值: true | false
hbm2ddl.auto
在ISessionFactory创建时,自动检查数据库结构,或者将数据库schema的DDL导出到数据库。
使用 create-drop时,在显式关闭ISessionFactory时,将drop掉数据库schema。
可用值: create | create-drop
use_proxy_validator
是否启用验证接口或者是类是否可以使用代理,默认开启。
(检查实体类的属性或者是方法是否被设置为Virtual)
可用值: true | false
transaction.factory_class
自定义ITransactionFactory的实现,默认为NHibernate内建的AdoNetTransactionFactory。
可用值: classname.of.TransactionFactory, assembly
其中SQL 方言是NHibernate针对不用的数据库生成SQL语句的策略。 
关系型数据库
NHibernate.Dialect.DB2Dialect
DB2 for iSeries (OS/400)
NHibernate.Dialect.DB2400Dialect
NHibernate.Dialect.IngresDialect
PostgreSQL
NHibernate.Dialect.PostgreSQLDialect
PostgreSQL 8.1
NHibernate.Dialect.PostgreSQL81Dialect
方言在PostgreSQL8.1中现在支持FOR UPDATE NOWAIT了。
PostgreSQL 8.2
NHibernate.Dialect.PostgreSQL82Dialect
方言在PostgreSQL8.2中现在支持在 DROP TABLE和DROP SEQUENCE中使用IF EXISTS关键字了。
MySQL 3 or 4
NHibernate.Dialect.MySQLDialect
NHibernate.Dialect.MySQL5Dialect
NHibernate.Dialect.Oracle8iDialect
NHibernate.Dialect.Oracle9Dialect
Oracle 10/11g
NHibernate.Dialect.Oracle10gDialect
Sybase Adaptive Server Enterprise
NHibernate.Dialect.SybaseDialect
Sybase Adaptive Server Anywhere
NHibernate.Dialect.SybaseAnywhereDialect
Microsoft SQL Server 2000
NHibernate.Dialect.MsSql2000Dialect
Microsoft SQL Server 2005
NHibernate.Dialect.MsSql2005Dialect
Microsoft SQL Server 2008
NHibernate.Dialect.MsSql2008Dialect
Microsoft SQL Server 2005 Everywhere Edition
NHibernate.Dialect.MsSqlCeDialect
Microsoft SQL Server 7
NHibernate.Dialect.MsSql7Dialect
NHibernate.Dialect.FirebirdDialect
把driver_class设置为 NHibernate.Driver.FirebirdClientDriver启用Firebird provider for .NET 2.0。
NHibernate.Dialect.SQLiteDialect
把driver_class设置为NHibernate.Driver.SQLite20Driver启用System.Data.SQLite provider for .NET 2.0。
Ingres 3.0
NHibernate.Dialect.IngresDialect
文章出处:
  内容摘要
    准备工作
    开发流程
    程序开发
  一、准备工作
    1.1开发环境
      开发工具:VS2008以上,我使用的是VS2010
      数据库:任意关系型数据库,我使用的是SQL Server 2005 Express
    1.2测试环境
      nunit 2.5.7
  二、开发流程
  NHibernate程序的开发流程是:
    (1).编写领域类与映射文件
    (2).使用NHibernate工具生成对应的数据库结构
    (3).编写DAO(数据库访问对象)
    (4).使用NUnit测试DAO(数据访问对象)的增、删、该、查方法
  三、程序开发
  3.1 建立Domain项目,如图3.1.1所示。
    编写类文件Product.cs
&///&&summary&&&&&///&商品&&&&///&&/summary&&&&&public&class&Product&&&&{&&&&&&&&///&&summary&&&&&&&&&///&ID&&&&&&&&///&&/summary&&&&&&&&&public&virtual&Guid&ID&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&编号&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Code&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&名称&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Name&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&规格&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&QuantityPerUnit&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&单位&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Unit&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&售价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&SellPrice&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&进价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&BuyPrice&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&备注&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Remark&{&get;&set;&}&&&&}
        
    编写映射文件Product.hbm.xml
Product.hbm.xml
&?xml&version="1.0"&encoding="utf-8"&?&&hibernate-mapping&xmlns="urn:nhibernate-mapping-2.2"&assembly="Domain"&namespace="Domain"&&&&class&name="Product"&table="T_Product"&lazy="true"&&&&&&&id&name="ID"&column="ID"&type="Guid"&&&&&&&&&generator&class="assigned"&/&&&&&&/id&&&&&&property&name="Code"&type="string"&&&&&&&&column&name="Code"&length="50"/&&&&&&/property&&&&&&property&name="Name"&type="string"&&&&&&&&column&name="Name"&length="50"/&&&&&&/property&&&&&&&&&&property&name="QuantityPerUnit"&type="string"&&&&&&&&column&name="QuantityPerUnit"&length="50"/&&&&&&/property&&&&&&property&name="Unit"&type="string"&&&&&&&&column&name="Unit"&length="50"/&&&&&&/property&&&&&&property&name="SellPrice"&type="decimal"&&&&&&&&column&name="SellPrice"&precision="14"&scale="2"/&&&&&&/property&&&&&&property&name="BuyPrice"&type="decimal"&&&&&&&&column&name="BuyPrice"&precision="14"&scale="2"/&&&&&&/property&&&&&&property&name="Remark"&type="string"&&&&&&&&column&name="Remark"&length="200"/&&&&&&/property&&&&/class&&/hibernate-mapping&
&  然后,将映射文件“Product.hbm.xml”的属性“生成方式”设置为“嵌入的资源”,如图3.1.2所示。
  3.2 建立名为“NHibernateTest”的项目,如图3.2.1所示
  引用程序集“Antlr3.Runtime.dll”,“Iesi.Collections.dll”,“NHibernate.dll”,“Remotion.Data.Linq.dll”,“nunit.framework.dll”,如图3.2.2所示
  然后音乐Domain项目,复制并粘贴NHibernate的配置模板到项目中,如图3.2.3所示
  图3.2.3
  修改该文件的属性为“始终复制”
hibernate.cfg.xml
&?xml&version="1.0"&encoding="utf-8"?&&!--&This&template&was&written&to&work&with&NHibernate.Test.Copy&the&template&to&your&NHibernate.Test&project&folder&and&rename&it&in&hibernate.cfg.xml&and&change&it&for&your&own&use&before&compile&tests&in&VisualStudio.--&&!--&This&is&the&System.Data.dll&provider&for&SQL&Server&--&&hibernate-configuration&&xmlns="urn:nhibernate-configuration-2.2"&&&&&&&session-factory&name="NHibernateTest"&&&&&&&&&&property&name="connection.driver_class"&NHibernate.Driver.SqlClientDriver&/property&&&&&&&&&&property&name="connection.connection_string"&&&&&&&server=.\SQLEXPRESS;database=NHibernateDuid=pwd=;&&&&&/property&&&&&&&&&&property&name="adonet.batch_size"&<span style="COLOR: #&/property&&&&&&&&&&property&name="show_sql"&true&/property&&&&&&&&&&property&name="dialect"&NHibernate.Dialect.MsSql2005Dialect&/property&&&&&&&&&&property&name="use_outer_join"&true&/property&&&&&&&&&&property&name="command_timeout"&<span style="COLOR: #&/property&&&&&&property&name="hbm2ddl.auto"&update&/property&&&&&&&&&&property&name="query.substitutions"&true&1,&false&0,&yes&'Y',&no&'N'&/property&&&&&&&&&&property&name="proxyfactory.factory_class"&NHibernate.ByteCode.LinFu.ProxyFactoryFactory,&NHibernate.ByteCode.LinFu&/property&&&&&&mapping&assembly="Domain"/&&&&&&/session-factory&&/hibernate-configuration&
  创建“NHibernateInit.cs”类文件,用于初始化数据库的表结构
NHibernateInit.cs
[TestFixture]&&&&public&class&NHibernateInit&&&&{&&&&&&&&[Test]&&&&&&&&public&void&InitTest()&&&&&&&&{&&&&&&&&&&&&var&cfg&=&new&NHibernate.Cfg.Configuration().Configure("Config/hibernate.cfg.xml");&&&&&&&&&&&&using&(ISessionFactory&sessionFactory&=&cfg.BuildSessionFactory())&{&}&&&&&&&&}&&&&}
  复制proxyfactory类的程序集“LinFu.DynamicProxy.dll”和“NHibernate.ByteCode.LinFu.dll”到项目中,并修改生成方式,如图3.2.4所示
  设置项目属性的启动操作,为“启动外部程序”,然后选择NUnit应用程序的路径。如图3.2.5所示。
  打开SQL Server Management Studio Express,创建名为“NHibernateDemo”的数据库,如图3.2.6
  启用NUnit,选择名称“NHibernateTest.dll”的程序集。如图3.2.7所示。接着,点击“run”按钮运行NUnit。
  这时,我们再打开数据库,就会发现,NHibernate已经为我们建立了“T_Product”表,如图3.2.8所示。
  3.3 编写DAO(数据库访问对象),建立名为“Dao”的项目。如图3.3.1所示。
  引用项目所需的程序集,接着编写IProductDao接口和 ProductDao类
ProductDao
&public&interface&IProductDao&&&&{&&&&&&&&object&Save(Product&entity);&&&&&&&&void&Update(Product&entity);&&&&&&&&void&Delete(Product&entity);&&&&&&&&Product&Get(object&id);&&&&&&&&Product&Load(object&id);&&&&&&&&IList&Product&&LoadAll();&&&&}&public&class&ProductDao&:&IProductDao&&&&{&&&&&&&&private&ISessionFactory&sessionF&&&&&&&&public&ProductDao()&&&&&&&&{&&&&&&&&&&&&var&cfg&=&new&NHibernate.Cfg.Configuration().Configure("Config/hibernate.cfg.xml");&&&&&&&&&&&&sessionFactory&=&cfg.BuildSessionFactory();&&&&&&&&}&&&&&&&&public&object&Save(Domain.Product&entity)&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&var&id&=&session.Save(entity);&&&&&&&&&&&&&&&&session.Flush();&&&&&&&&&&&&&&&&return&&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public&void&Update(Domain.Product&entity)&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&session.Update(entity);&&&&&&&&&&&&&&&&session.Flush();&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public&void&Delete(Domain.Product&entity)&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&session.Delete(entity);&&&&&&&&&&&&&&&&session.Flush();&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public&Domain.Product&Get(object&id)&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&return&session.Get&Domain.Product&(id);&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public&Domain.Product&Load(object&id)&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&return&session.Load&Domain.Product&(id);&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public&IList&Domain.Product&&LoadAll()&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&return&session.Query&Domain.Product&().ToList();&&&&&&&&&&&&}&&&&&&&&}}
  然后在测试项目“NHibernateTest”中编写测试类“ProductDaoTest”。
ProductDaoTest
[TestFixture]&&&&public&class&ProductDaoTest&&&&{&&&&&&&&private&IProductDao&productD&&&&&&&&[SetUp]&&&&&&&&public&void&Init()&&&&&&&&{&&&&&&&&&&&&productDao&=&new&ProductDao();&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&SaveTest()&&&&&&&&{&&&&&&&&&&&&var&product&=&new&Domain.Product&&&&&&&&&&&&{&&&&&&&&&&&&&&&&ID&=&Guid.NewGuid(),&&&&&&&&&&&&&&&&BuyPrice&=&10M,&&&&&&&&&&&&&&&&Code&=&"ABC123",&&&&&&&&&&&&&&&&Name&=&"电脑",&&&&&&&&&&&&&&&&QuantityPerUnit&=&"<span style="COLOR: #x1",&&&&&&&&&&&&&&&&SellPrice&=&11M,&&&&&&&&&&&&&&&&Unit&=&"台"&&&&&&&&&&&&};&&&&&&&&&&&&var&obj&=&this.productDao.Save(product);&&&&&&&&&&&&Assert.NotNull(obj);&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&UpdateTest()&&&&&&&&{&&&&&&&&&&&&var&product&=&this.productDao.LoadAll().FirstOrDefault();&&&&&&&&&&&&Assert.NotNull(product);&&&&&&&&&&&&product.SellPrice&=&12M;&&&&&&&&&&&&Assert.AreEqual(12M,&product.SellPrice);&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&DeleteTest()&&&&&&&&{&&&&&&&&&&&&var&product&=&this.productDao.LoadAll().FirstOrDefault();&&&&&&&&&&&&Assert.NotNull(product);&&&&&&&&&&&&var&id&=&product.ID;&&&&&&&&&&&&this.productDao.Delete(product);&&&&&&&&&&&&Assert.Null(this.productDao.Get(id));&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&GetTest()&&&&&&&&{&&&&&&&&&&&&var&product&=&this.productDao.LoadAll().FirstOrDefault();&&&&&&&&&&&&Assert.NotNull(product);&&&&&&&&&&&&var&id&=&product.ID;&&&&&&&&&&&&Assert.NotNull(this.productDao.Get(id));&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&LoadTest()&&&&&&&&{&&&&&&&&&&&&var&product&=&this.productDao.LoadAll().FirstOrDefault();&&&&&&&&&&&&Assert.NotNull(product);&&&&&&&&&&&&var&id&=&product.ID;&&&&&&&&&&&&Assert.NotNull(this.productDao.Get(id));&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&LoadAllTest()&&&&&&&&{&&&&&&&&&&&&var&count&=&this.productDao.LoadAll().C&&&&&&&&&&&&Assert.True(count&&&<span style="COLOR: #);&&&&&&&&}}
  最后运行NUnit测试该项目。效果如图3.3.2所示。
  图3.3.2
  好了,一个NHibernate完整的项目就做完了。从中我们可以发现,此应用程序项目没有编写一条SQL语句,就能实现数据的增、删、该、查。
  这样一来,便简化了我们的项目开发。O(∩_∩)O~
  出处:
  内容摘要
    持久对象的状态的概念
    持久对象的状态Demo
  一、持久对象的状态的概念  
  在NHibernate中有三种状态,对它的深入理解,才能更好的理解NHibernate的运行机理,刚开始不太注意这些概念,后来发现它是重要的。对于NHibernate和SQL的关系有更好的理解;对于理解需要持久化的.NET对象,在它的生命周期中三种状态之间的互相转化有很大帮助。如图1.1所示
临时态(Transient):用new创建的对象,它没有持久化,没有纳入Session中,随时可以被垃圾回收,处于此状态的对象叫临时对象。特点:数据库中没有与之对应的记录;
持久态(Persistent):已经持久化,加入到了Session缓存中。通过NHibernate保存的对象或通过Get/Load等方法获取出的对象,其对象没有脱离Session的管理,处于此状态的对象叫持久对象;
游离态(Detached):持久化对象脱离了Session的对象。如Session缓存被清空的对象。特点:已经持久化,但不在Session缓存中。处于此状态的对象叫游离对象;
  二、持久对象的状态Demo
  2.1 准备工作
  (1)建立名为“NHibernateTest”的项目
  (2)引用相应的程序集并引入上节课的“Domain”项目。
  (3)复制上节课的“hibernate.cfg.xml”配置模板
hibernate.cfg.xml
&?xml&version="1.0"&encoding="utf-8"?&&!--&This&template&was&written&to&work&with&NHibernate.Test.Copy&the&template&to&your&NHibernate.Test&project&folder&and&rename&it&in&hibernate.cfg.xml&and&change&it&for&your&own&use&before&compile&tests&in&VisualStudio.--&&!--&This&is&the&System.Data.dll&provider&for&SQL&Server&--&&hibernate-configuration&&xmlns="urn:nhibernate-configuration-2.2"&&&&&&&session-factory&name="NHibernateTest"&&&&&&&&&&property&name="connection.driver_class"&NHibernate.Driver.SqlClientDriver&/property&&&&&&&&&&property&name="connection.connection_string"&&&&&&&server=.\SQLEXPRESS;database=NHibernateDuid=pwd=;&&&&&/property&&&&&&&&&&property&name="adonet.batch_size"&<span style="COLOR: #&/property&&&&&&&&&&property&name="show_sql"&true&/property&&&&&&&&&&property&name="dialect"&NHibernate.Dialect.MsSql2005Dialect&/property&&&&&&&&&&property&name="use_outer_join"&true&/property&&&&&&&&&&property&name="command_timeout"&<span style="COLOR: #&/property&&&&&&property&name="hbm2ddl.auto"&update&/property&&&&&&&&&&property&name="query.substitutions"&true&1,&false&0,&yes&'Y',&no&'N'&/property&&&&&&&&&&property&name="proxyfactory.factory_class"&NHibernate.ByteCode.LinFu.ProxyFactoryFactory,&NHibernate.ByteCode.LinFu&/property&&&&&&mapping&assembly="Domain"/&&&&&&/session-factory&&/hibernate-configuration&
  (4)引用“log4net.dll”并配置App.config,用于输出日志 
App.config
&?xml&version="1.0"?&&configuration&&&&configSections&&&&&&section&name="log4net"&type="log4net.Config.Log4NetConfigurationSectionHandler,&log4net"&/&&&&/configSections&&&&!--log4net配置--&&&&log4net&debug="true"&&&&&&appender&name="LogFileAppender"&type="log4net.Appender.FileAppender"&&&&&&&&param&name="File"&value="Logs\Log.log"&/&&&&&&&&param&name="datePattern"&value="MM-dd&HH:mm"&/&&&&&&&&param&name="AppendToFile"&value="true"&/&&&&&&&&layout&type="log4net.Layout.PatternLayout"&&&&&&&&&&param&name="ConversionPattern"&value="%d&[%t]&%-5p&%c&[%x]&-&%m%n"&/&&&&&&&&/layout&&&&&&/appender&&&&&&appender&name="HttpTraceAppender"&type="log4net.Appender.ASPNetTraceAppender"&&&&&&&&layout&type="log4net.Layout.PatternLayout"&&&&&&&&&&param&name="ConversionPattern"&value="%d&[%t]&%-5p&%c&[%x]&-&%m%n"&/&&&&&&&&/layout&&&&&&/appender&&&&&&appender&name="EventLogAppender"&type="log4net.Appender.EventLogAppender"&&&&&&&&layout&type="log4net.Layout.PatternLayout"&&&&&&&&&&param&name="ConversionPattern"&value="%d&[%t]&%-5p&%c&[%x]&-&%m%n"&/&&&&&&&&/layout&&&&&&/appender&&&&&&appender&name="RollingLogFileAppender"&type="log4net.Appender.RollingFileAppender"&&&&&&&&param&name="File"&value="Logs/Log.log"&/&&&&&&&&param&name="AppendToFile"&value="true"&/&&&&&&&&param&name="MaxSizeRollBackups"&value="10"&/&&&&&&&&param&name="MaximumFileSize"&value="100K"&/&&&&&&&&param&name="RollingStyle"&value="Size"&/&&&&&&&&param&name="StaticLogFileName"&value="true"&/&&&&&&&&layout&type="log4net.Layout.PatternLayout"&&&&&&&&&&param&name="ConversionPattern"&value="%d&[%t]&%-5p&%c&[%x]&-&%m%n"&/&&&&&&&&/layout&&&&&&/appender&&&&&&root&&&&&&&&level&value="ALL"&/&&&&&&&&appender-ref&ref="RollingLogFileAppender"&/&&&&&&/root&&&&/log4net&&&&startup&&&&&&supportedRuntime&version="v4.0"&sku=".NETFramework,Version=v4.0"/&&&&/startup&&/configuration&
  (5)复制“LinFu.DynamicProxy.dll”和“NHibernate.ByteCode.LinFu.dll”文件,粘贴到项目中。
  (6)增加用于单元测试的类文件“LifecycleTest.cs”
LifecycleTest.cs
&&&&[TestFixture]&&&&public&class&LifecycleTest&&&&{&&&&&&&&private&ISessionFactory&sessionF&&&&&&&&public&LifecycleTest()&&&&&&&&{&&&&&&&&&&&&log4net.Config.XmlConfigurator.Configure();&&&&&&&&}&&&&&&&&[SetUp]&&&&&&&&public&void&Init()&&&&&&&&{&&&&&&&&&&&&var&cfg&=&new&NHibernate.Cfg.Configuration().Configure("Config/hibernate.cfg.xml");&&&&&&&&&&&&sessionFactory&=&cfg.BuildSessionFactory();&&&&&&&&}&&&&&}
  如图2.1.1所示,准备完成后,便可以开始我们的演示。
  2.2 临时态(Transient)到持久态(Persistent)
  先new一个对象,该对象的状态为Transient,然后调用Save()方法将该对象持久化到数据库中,该对象的状态变为Persistent。在未关闭Session前,修改该对象的属性,最后提交事务。
TransientToPersistentTest
&&&&&&&&///&&summary&&&&&&&&&///&临时态--&持久态&&&&&&&&///&&/summary&&&&&&&&&[Test]&&&&&&&&public&void&TransientToPersistentTest()&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&//Transient&&&&&&&&&&&&&&&&&&&&var&product&=&new&Product&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&ID&=&Guid.NewGuid(),&&&&&&&&&&&&&&&&&&&&&&&&BuyPrice&=&10M,&&&&&&&&&&&&&&&&&&&&&&&&Code&=&"ABC123",&&&&&&&&&&&&&&&&&&&&&&&&Name&=&"电脑",&&&&&&&&&&&&&&&&&&&&&&&&QuantityPerUnit&=&"<span style="COLOR: #x1",&&&&&&&&&&&&&&&&&&&&&&&&SellPrice&=&11M,&&&&&&&&&&&&&&&&&&&&&&&&Unit&=&"台"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&};&&&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&session.Save(product);&&&&&&&&&&&&&&&&&&&&&&&&//保存记录后修改数据,观察数据库中数据的变化&&&&&&&&&&&&&&&&&&&&&&&&product.SellPrice&=&12M;&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}
  运行效果如图2.2.1所示,首先生成了insert into语句,然后生成了update语句。
  一开始,Product的SellPrice属性,我设置为“11M”,然后调用“Save”方法持久化“Product”对象,接下来修改SellPrice属性到“12M”。最后让我们打开数据库,看一下里面的数据到底是“11M”,还是“12M”。如图2.2.2所示,数据是“12M”。
  这时,我们心里便产生了一个疑问:把Product的SellPrice属性从“11M”修改为“12M”后,并没有调用Save()或者Update()的方法,为什么数据库中的数据会变呢?
  这是因为,当对象处于Persistent状态,并没有脱离Session管理时,其属性发生改变后,数据库相对应的记录会与之同步。
  2.3 持久态(Persistent)到游离态(Detached),再到持久态(Persistent)
PersistentToTestDetached
&///&&summary&&&&&&&&&///&持久态--&游离态--&持久态&&&&&&&&///&&/summary&&&&&&&&&[Test]&&&&&&&&public&void&PersistentToTestDetached()&&&&&&&&{&&&&&&&&&&&&//Transient&&&&&&&&&&&&var&product&=&new&Product&&&&&&&&&&&&{&&&&&&&&&&&&&&&&ID&=&Guid.NewGuid(),&&&&&&&&&&&&&&&&BuyPrice&=&10M,&&&&&&&&&&&&&&&&Code&=&"ABC123",&&&&&&&&&&&&&&&&Name&=&"电脑",&&&&&&&&&&&&&&&&QuantityPerUnit&=&"<span style="COLOR: #x1",&&&&&&&&&&&&&&&&SellPrice&=&11M,&&&&&&&&&&&&&&&&Unit&=&"台"&&&&&&&&&&&&};&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&session.Save(product);&&&&&&&&&&&&&&&&&&&&&&&&product.SellPrice&=&12M;&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&&&&&//Detached&&&&&&&&&&&&product.SellPrice&=&13M;&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&session.Update(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}
  运行效果如图2.3.1所示。当对象处于游离态(Detached)时,修改其属性,是不会与数据库发生同步的。调用Update()方法后,对象则变回持久态(Persistent)。
  2.4 Get方法得到持久态(Persistent)
  通过Get()方法获取持久态(Persistent)对象,然后修改其属性,观察是否与数据库发生同步。运行效果如图2.4.1所示,先生成insert into语句,然后生成select语句,最后生成update语句。
  我们能够得出结论,通过Get()方法,是可以得到持久态(Persistent)对象的。
  2.5 Get和Load()方法的区别
  我们模拟一个数据库中不存在的对象,分别调用Get和Load()方法来测试产生的效果。
  Get方法的代码如下:
&&&&&&&&///&&summary&&&&&&&&&///&查询空记录&&&&&&&&///&&/summary&&&&&&&&&[Test]&&&&&&&&public&void&GetNullTest()&&&&&&&&{&&&&&&&&&&&&Guid&id&=&Guid.NewGuid();&&&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&var&product&=&session.Get&Product&(id);&&&&&&&&&&&&&&&&&&&&&&&&Console.WriteLine("调用&Get()方法");&&&&&&&&&&&&&&&&&&&&&&&&//断言为空&&&&&&&&&&&&&&&&&&&&&&&&Assert.Null(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}
  Get()方法的运行效果,如图2.5.1所示。调用Get()方法后,数据库中不存在的对象返回值为null,并且一但调用Get()方法,就会生成SQL语句。
  Load()方法的代码如下:
&&&&&&///&&summary&&&&&&&&&///&查询空记录&&&&&&&&///&&/summary&&&&&&&&&[Test]&&&&&&&&public&void&LoadTest()&&&&&&&&{&&&&&&&&&&&&Guid&id&=&Guid.NewGuid();&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&var&product&=&session.Load&Product&(id);&&&&&&&&&&&&&&&&&&&&&&&&Console.WriteLine("调用&Load()方法");&&&&&&&&&&&&&&&&&&&&&&&&//断言为空&&&&&&&&&&&&&&&&&&&&&&&&Assert.NotNull(product);&&&&&&&&&&&&&&&&&&&&&&&&//当查看其属性时,则会生成SQL语句&&&&&&&&&&&&&&&&&&&&&&&&string&name&=&product.N&&&&&&&&&&&&&&&&&&&&&&&&Assert.NotNull(name);&&//断言name不为空&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}
  Load()方法的运行效果,如图2.5.2所示。调用Load()方法查询数据库中不存在的对象,返回值不为空;当调用Load()方法时,不立刻产生SQL语句,查看其属性后才产生SQL语句,并且查看数据库中不存在对象的属性时会抛出异常。原因是调用Load()方法会返回一个“代理类”,这是NHibernate的一个重要的特性——延迟加载。
 延迟加载(lazy load)也叫“懒加载”,是NHibernate关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出SQL语句进行查询。 延迟加载的有效期是在Session打开的情况下,当Session关闭后,会报异常。NHibernate的代理对象是由第三方组件“Antlr3.Runtime”提供的。
  2.6 Delete()方法
  先得到一个持久态(Persistent)对象,然后调用Delete()方法删除该对象,这时该对象变回临时态(Transient)
  代码如下:
&&&&&&&&[Test]&&&&&&&&public&void&DeleteTest()&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&//Transient&&&&&&&&&&&&&&&&&&&&var&product&=&new&Product&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&ID&=&Guid.NewGuid(),&&&&&&&&&&&&&&&&&&&&&&&&BuyPrice&=&10M,&&&&&&&&&&&&&&&&&&&&&&&&Code&=&"ABC123",&&&&&&&&&&&&&&&&&&&&&&&&Name&=&"电脑",&&&&&&&&&&&&&&&&&&&&&&&&QuantityPerUnit&=&"<span style="COLOR: #x1",&&&&&&&&&&&&&&&&&&&&&&&&SellPrice&=&11M,&&&&&&&&&&&&&&&&&&&&&&&&Unit&=&"台"&&&&&&&&&&&&&&&&&&&&};&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&session.Save(product);&&&&&&&&&&&&&&&&&&&&&&&&//Transient&&&&&&&&&&&&&&&&&&&&&&&&session.Delete(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}
  运行效果如图2.6.1所示,先生成insert into语句,再生成delete语句。
  2.7 Update()方法
  先手动打造new一个数据库中存在的游离态(Detached)对象,然后直接调用Update()方法将对象的状态设置为持久态(Persistent)。
  代码如下:
&&&&&&&&[Test]&&&&&&&&public&void&UpdateTest()&&&&&&&&{&&&&&&&&&&&&Guid&id&=&Guid.NewGuid();&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&//Transient&&&&&&&&&&&&&&&&&&&&var&product&=&new&Product&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&ID&=&id,&&&&&&&&&&&&&&&&&&&&&&&&BuyPrice&=&10M,&&&&&&&&&&&&&&&&&&&&&&&&Code&=&"ABC123",&&&&&&&&&&&&&&&&&&&&&&&&Name&=&"电脑",&&&&&&&&&&&&&&&&&&&&&&&&QuantityPerUnit&=&"<span style="COLOR: #x1",&&&&&&&&&&&&&&&&&&&&&&&&SellPrice&=&11M,&&&&&&&&&&&&&&&&&&&&&&&&Unit&=&"台"&&&&&&&&&&&&&&&&&&&&};&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&session.Save(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&//Detached&&&&&&&&&&&&&&&&&&&&var&product&=&new&Product&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&ID&=&id,&&&&&&&&&&&&&&&&&&&&&&&&Code&=&"ABC456",&&&&&&&&&&&&&&&&&&&&};&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&//Persistent&&&&&&&&&&&&&&&&&&&&&&&&session.Update(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}
  运行效果如图2.7.1所示,生成了update语句,并已经修改了对应的记录。有的朋友就会问,为什么new的时候也能得到游离态(Detached)对象?因为判断是否为游离态(Detached)对象,是根据数据库中是否存在与之对应的记录定夺的。
&  出处:
  内容摘要
    持久化类
    持久化生命周期中的回调
    合法性验证回调
    一、持久化类(Persistent Classes)
      1.1 什么是持久化类
  回答这个问题之前先回答什么是持久化。所谓的持久化就是把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。然而持久化类就是持久化数据的载体,在应用程序中,用来实现业务问题实体的(如,在电子商务应用程序中的Customer和Order) 类就是持久化类。不能认为所有的持久化类的实例都是持久的状态——一个实例的状态也可能 是瞬时的或脱管的。 如果这些持久化类遵循一些简单的规则,NHibernate能够工作得更好,这些规则也被称作 简单传统CLR对象(POCO:Plain Old CLR Object)编程模型。
  之前用到的“Product”类,就是持久化类
using&Susing&System.Collections.Gusing&System.Lusing&System.Tnamespace&Domain{&&&&///&&summary&&&&&///&商品&&&&///&&/summary&&&&&public&class&Product&&&&{&&&&&&&&///&&summary&&&&&&&&&///&ID&&&&&&&&///&&/summary&&&&&&&&&public&virtual&Guid&ID&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&编号&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Code&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&名称&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Name&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&规格&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&QuantityPerUnit&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&单位&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Unit&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&售价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&SellPrice&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&进价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&BuyPrice&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&备注&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Remark&{&get;&set;&}&&&&}}
  然而持久化类须满足一定的规则。
      1.2持久化类的规则
实现一个默认的(即无参数的)构造方法(constructor)
提供一个标识属性(identifier property)(可选)
使用非密封(non-sealed)类以及虚方法(virtual methods) (可选)
  二、持久化生命周期中的回调
  2.1 ILifecycle接口介绍
  持久化类可以实现ILifecycle接口,它可以提供一些用于回调的方法, 可以让持久化对象在Save或Load之后,或者在Delete或Update之前进行必要的初始化与清除步骤。
  让我们看一下ILifecycle接口 
ILifecycle
&&&&public&interface&ILifecycle&&&&{&&&&&&&&LifecycleVeto&OnDelete(ISession&s);&&&&&&&&void&OnLoad(ISession&s,&object&id);&&&&&&&&LifecycleVeto&OnSave(ISession&s);&&&&&&&&LifecycleVeto&OnUpdate(ISession&s);&&&&}
  其中ILifecycle接口的方法如下:
OnSave - 在对象即将被save或者insert的时候回调
OnUpdate - 在对象即将被update的时候回调(也就是对象被传递给ISession.Update()的时候)
OnDelete - 在对象即将被delete(删除)的时候回调
OnLoad - 在对象刚刚被load(装载)后的时候回调
  如果OnSave(), OnUpdate() 或者 OnDelete()返回LifecycleVeto.Veto,那么操作就被悄悄地取消了。 如果其中抛出了CallbackException异常,操作被取消,这个异常会被继续传递给应用程序。
  2.2 ILifecycle的demo
  实体:  
///&&summary&&&&&///&商品&&&&///&&/summary&&&&&public&class&Product&:&ILifecycle&&&&{&&&&&&&&///&&summary&&&&&&&&&///&ID&&&&&&&&///&&/summary&&&&&&&&&public&virtual&Guid&ID&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&编号&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Code&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&名称&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Name&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&规格&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&QuantityPerUnit&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&单位&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Unit&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&售价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&SellPrice&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&进价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&BuyPrice&{&get;&set;&}&&&&&&&&///&&summary&&&&&&&&&///&备注&&&&&&&&///&&/summary&&&&&&&&&public&virtual&string&Remark&{&get;&set;&}&&&&&&&&public&virtual&LifecycleVeto&OnDelete(NHibernate.ISession&s)&&&&&&&&{&&&&&&&&&&&&Console.WriteLine("您调用了Delete()方法!");&&&&&&&&&&&&return&LifecycleVeto.NoV&&&&&&&&}&&&&&&&&public&virtual&void&OnLoad(NHibernate.ISession&s,&object&id)&&&&&&&&{&&&&&&&&&&&&Console.WriteLine("您调用了Load()方法!");&&&&&&&&}&&&&&&&&public&virtual&LifecycleVeto&OnSave(NHibernate.ISession&s)&&&&&&&&{&&&&&&&&&&&&Console.WriteLine("您调用了Save()方法!");&&&&&&&&&&&&return&LifecycleVeto.NoV&&&&&&&&}&&&&&&&&public&virtual&LifecycleVeto&OnUpdate(NHibernate.ISession&s)&&&&&&&&{&&&&&&&&&&&&Console.WriteLine("您调用了Update()方法!");&&&&&&&&&&&&return&LifecycleVeto.NoV&&&&&&&&}&&&&}
  单元测试:
LifecycleTest
[TestFixture]&&&&public&class&LifecycleTest&&&&{&&&&&&&&private&ISessionFactory&sessionF&&&&&&&&private&static&readonly&Guid&s_id&=&Guid.NewGuid();&&&&&&&&[SetUp]&&&&&&&&public&void&Init()&&&&&&&&{&&&&&&&&&&&&var&cfg&=&new&NHibernate.Cfg.Configuration().Configure("Config/hibernate.cfg.xml");&&&&&&&&&&&&sessionFactory&=&cfg.BuildSessionFactory();&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&SaveTest()&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&var&product&=&new&Product&&&&&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&ID&=&s_id,&&&&&&&&&&&&&&&&&&&&&&&&&&&&BuyPrice&=&10M,&&&&&&&&&&&&&&&&&&&&&&&&&&&&Code&=&"ABC123",&&&&&&&&&&&&&&&&&&&&&&&&&&&&Name&=&"电脑",&&&&&&&&&&&&&&&&&&&&&&&&&&&&QuantityPerUnit&=&"<span style="COLOR: #x1",&&&&&&&&&&&&&&&&&&&&&&&&&&&&SellPrice&=&11M,&&&&&&&&&&&&&&&&&&&&&&&&&&&&Unit&=&"台"&&&&&&&&&&&&&&&&&&&&&&&&};&&&&&&&&&&&&&&&&&&&&&&&&session.Save(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&UpdateTest()&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&var&product&=&session.Load&Product&(s_id);&&&&&&&&&&&&&&&&&&&&&&&&product.BuyPrice&=&12M;&&&&&&&&&&&&&&&&&&&&&&&&session.Update(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&[Test]&&&&&&&&public&void&DeleteTest()&&&&&&&&{&&&&&&&&&&&&using&(ISession&session&=&this.sessionFactory.OpenSession())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&using&(ITransaction&tran&=&session.BeginTransaction())&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&var&product&=&session.Load&Product&(s_id);&&&&&&&&&&&&&&&&&&&&&&&&session.Delete(product);&&&&&&&&&&&&&&&&&&&&&&&&mit();&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&catch&(Exception&ex)&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&tran.Rollback();&&&&&&&&&&&&&&&&&&&&&&&&throw&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}&&&&}
  运行SaveTest()方法的效果,如图2.2.1所示。
  运行UpdateTest()方法的效果,如图2.2.2所示。奇怪的是OnUpdate()回调没有工作,这是因为在NHibernate 1.x 以后的版本,ILifecycle接口已经不建议使用了。
  运行DeleteTest()方法的效果,如图2.2.3所示。
  三、合法性验证回调
  合法性验证(IValidatable)回调是在持久化类在保存其持久化状态前进行合法性检查的接口。
public&interface&IValidatable{&&&&&&&&void&Validate();}
&  如果发现对象违反了某条规则,应该抛出一个ValidationFailure异常。在Validatable实例的Validate()方法内部不应该改变它的状态。
和ILifecycle接口的回调方法不同,Validate()可能在任何时间被调用。应用程序不应该把Validate()调用和商业功能联系起来。
  实现代码如下:
public&class&Product&:&IValidatable&&&&{&&&&&&&&....&&&&&&&&///&&summary&&&&&&&&&///&进价&&&&&&&&///&&/summary&&&&&&&&&public&virtual&decimal&BuyPrice&{&get;&set;&}&&&&&&&&public&virtual&void&Validate()&&&&&&&&{&&&&&&&&&&&&if&(this.BuyPrice&&=&12M)&&&&&&&&&&&&{&&&&&&&&&&&&&&&&throw&new&ValidationFailure("进货价格太高,无法受理!");&&&&&&&&&&&&}&&&&&&&&}&&&&}
  运行效果如图3.1所示
  总结:目前NHibernate 3.0版本中不建议使用ILifecycle和IValidatable接口。因为这样NHibernate框架就会对持久化类产生侵入性。
  出处:
  内容摘要
  映射定义概括
  基本映射常用标签
  NHibernate的类型
  一、映射定义概括
  1.1 映射定义(Mapping declaration)
  对象和关系数据库之间的映射是用一个XML文档(XML document)来定义的。这个映射文档被设计为易读的,并且可以手工修改。映射语言是以对象为中心的, 意味着映射是按照持久化类的定义来创建的,而非表的定义。
  让我们打开上节课的映射例子:
Product.hbm.xml
&?xml&version="1.0"&encoding="utf-8"&?&&hibernate-mapping&xmlns="urn:nhibernate-mapping-2.2"&assembly="Domain"&namespace="Domain"&&&&class&name="Product"&table="T_Product"&lazy="true"&&&&&&&id&name="ID"&column="ID"&type="Guid"&&&&&&&&&generator&class="assigned"&/&&&&&&/id&&&&&&property&name="Code"&type="string"&&&&&&&&column&name="Code"&length="50"/&&&&&&/property&&&&&&property&name="Name"&type="string"&&&&&&&&column&name="Name"&length="50"/&&&&&&/property&&&&&&&&&&property&name="QuantityPerUnit"&type="string"&&&&&&&&column&name="QuantityPerUnit"&length="50"/&&&&&&/property&&&&&&property&name="Unit"&type="string"&&&&&&&&column&name="Unit"&length="50"/&&&&&&/property&&&&&&property&name="SellPrice"&type="decimal"&&&&&&&&column&name="SellPrice"&precision="14"&scale="2"/&&&&&&/property&&&&&&property&name="BuyPrice"&type="decimal"&&&&&&&&column&name="BuyPrice"&precision="14"&scale="2"/&&&&&&/property&&&&&&property&name="Remark"&type="string"&&&&&&&&column&name="Remark"&length="200"/&&&&&&/property&&&&/class&&/hibernate-mapping&
&  其中xmlns为xml命名空间,我们能够在NHibernate的分发包src\nhibernate-mapping.xsd里找到XSD文件。我们可以将.xsd文件拷贝到Visual Studio安装目录的\Xml\Schemas中,以便带来NHibernate持久化类配置的提示功能。
  二、基本映射常用标签
  作为NHibernate这个ORM框架来说,一个实体类对应的是数据库中的一张表;类中的一个属性对应表中的一个字段;一个对象对应的是表中的一条记录。
  2.1 hibernate-mapping
  &hibernate-mapping&标签是NHibernate映射文件的根节点。
  &hibernate-mapping&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&  && && schema="schemaName"&&&&&&&&&&&&&&&&&&&&&&&& 数据库schema名称。
&&&&&&&& default-cascade="none|save-update"&&&&&&默认的级联风格,(可选 - 默认为 none):。
&&&&&&&& auto-import="true|false"&&&     &&&&& 指定我们在使用查询语句的时候是否可以使用非全限定名。  &
&&&&&&&& assembly="AssemblyName"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&   
&&&&&&&& namespace="Namespace"     &&&&&&& 指定映射文件中的类的应用程序集名称和其所在的名称空间名,用来生成类的非全限定名。        
  2.2 class
  &class&标签是定义一个持久化类的。  &class
name="ClassName"
持久化类的类名,这里可以是类的全名。
table="tableName"
对应的数据库表名。
discriminator-value="discriminator_value"
辨别值,一个用于区分不同的子类的值,在多态行为时使用(在后面继承映射的课程中会讲到)。
mutable="true|false"
表明该类的实例可变。
schema="owner"
覆盖在根元素中指定的schema名字。
proxy="ProxyInterface"
指定一个接口,在延迟装载时作为代理使用。你可以在这里使用该类自己的名字。
dynamic-update="true|false"
指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。
dynamic-insert="true|false"
指定用于 INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。
select-before-update="true|false"
指定NHibernate除非确定对象的确被修改了,UPDATE操作。
polymorphism="implicit|explicit"
界定是隐式还是显式的使用查询多态。
where="arbitrary sql where condition"
指定一个附加的SQL WHERE 条件,在抓取这个类的对象时会一直增加这个条件。
persister="PersisterClass"
指定一个定制的 IClassPersister。
batch-size="N"
指定一个用于根据标识符抓取实例时使用的"batch size"(批次抓取数量),默认值为1。
optimistic-lock="none|version|dirty|all"
乐观锁定,决定乐观锁定的策略。
lazy="true|false"
是否启用延迟加载。
abstract="true|false"
是否为抽象类。
&  2.3 id
  &id&标签定义了该属性到数据库表主键字段的映射。
  &id&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
  & name="PropertyName"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &标识属性的名字。&&&&&&& type="typename"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& NHibernate类型的名字&&&&&&& column="column_name"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 主键字段的名字。&&&&&&& unsaved-value="any|none|null|id_value"&&&&&&&& 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。&&&&&&& access="field|property|nosetter|ClassName"&& &NHibernate用来访问属性值的策略。&&&&&&& &generator class="generatorClass"/&  &/id&
&  generator:主键生成策略。NHibernate提供了以下几种生成策略:
  2.4 composite-id
  &composite-id&为联合主键。
  &composite-id&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& name="PropertyName"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& class="ClassName"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 联合主键类的类名。&&&&&&& unsaved-value="any|none"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&& access="field|property|nosetter|ClassName"&&&&&&&& &key-property name="PropertyName" type="typename" column="column_name"/&&&&&&&&&&&&& 联合主键的属性&&&&&&& &key-many-to-one name="PropertyName class="ClassName" column="column_name"/&&&&&& 联合主键多对一属性&&&&&&& ......  &/composite-id&
  注意的是,若使用联合主键,你的持久化类必须重载 Equals()和GetHashCode()方法。例子如下:
&?xml&version="1.0"&encoding="utf-8"&?&&hibernate-mapping&xmlns="urn:nhibernate-mapping-2.2"&assembly="Domain"&namespace="Domain"&&&&class&name="Product"&table="T_Product"&lazy="true"&&&&&&&&&&&composite-id&name="ID"&class="ProductID"&&&&&&&&key-property&name="Name"&type="string"&&&&&&&&&&column&name="Name"&length="50"/&&&&&&&&/key-property&&&&&&&&key-property&name="QuantityPerUnit"&type="string"&&&&&&&&&&column&name="QuantityPerUnit"&length="50"/&&&&&&&&/key-property&&&&&&/composite-id&&&&&&property&name="Unit"&type="string"&&&&&&&&column&name="Unit"&length="50"/&&&&&&/property&&&&&&property&name="SellPrice"&type="decimal"&&&&&&&&column&name="SellPrice"&precision="14"&scale="2"/&&&&&&/property&&&&&&property&name="BuyPrice"&type="decimal"&&&&&&&&column&name="BuyPrice"&precision="14"&scale="2"/&&&&&&/property&&&&&&property&name="Remark"&type="string"&&&&&&&&column&name="Remark"&length="200"/&&&&&&/property&&&&/class&&/hibernate-mapping&
using&Susing&System.Collections.Gusing&System.Lusing&System.Tnamespace&Domain{&&&&public&class&Product&&&&{&&&&&&&&public&virtual&ProductID&ID&{&get;&set;&}&&&&&&&&public&virtual&string&Unit&{&get;&set;&}&&&&&&&&p

我要回帖

更多关于 lazyload 占位图设置 的文章

 

随机推荐