NHibernate搭配Access的问题.pdf
-
资源ID:74132419
资源大小:319.71KB
全文页数:8页
- 资源格式: PDF
下载积分:11.9金币
快捷下载
![游客一键下载](/images/hot.gif)
会员登录下载
微信登录下载
三方登录下载:
微信扫一扫登录
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
|
NHibernate搭配Access的问题.pdf
NHibernateNHibernate 搭配搭配 AccessAccess 的问题的问题近日想学习一下 NHibernate,以用在最新的一套大型系统上。想想不如先做一个小网站来练练手,不过之前还是得先看看 NHibernate 的 使用方法。搜索了几篇入门文章,包括官方网站的 First Step,然后就开始写了。本想使用Access 数据库,结果是一直失败,一开始是连 Configuration 都无法生成,后来又是写入数据库错误。后来改成使用 Sql server2000,结果很顺序的就通过了。再改成Access,又没有了头绪。最后经历了千辛万苦啊,终于算是通过了。总结如下:使用 Access 数据库的组件在官方下载的NHibernate-contrib文件里,有个NHibernate.JetDriver.dll,这个文件也是必须的。其实,在app.config 文件里加入NHibernate 属性的语句是:那个 dialect 和 driver_class 的值里面前面是类名称,后面是命名空间名称,中间用逗号分开,不可缺少。以前查到的一些资料里都没有这一步,所以一直失败。最后还有一个问题,用户表里面的 LastLogon 是个日期时间字段,类里面字段的属性也设成日期时间,插入的时候报错,把类里面的字段改成 string 就 可以了,可能是因为插入的时候没有加引号的问题。还有密码字段如果字段名为Password,同样插入出错,这个应该是字段名跟关键字冲突的问题,看来作 者没有考虑到把字段名括起来的问题。但是我一直没有办法显示出最终要执行的sql 语句,所以也一直没有办法确定错误原因。不过有了以上内容,应该足够写完 整个程序了。测试了一下性能,点击按钮到返回,要2 秒多,明显有点慢,做了一个10000 个新数据,然后一次写入,用了 20 秒才写完,有点不可接受了。回头试一下直接用OleDb 写入的速度比较一下吧。对于昨天的问题,继续研究了一下。经过一阵搜索,受到了另一位仁兄的启发。现在的速度慢,跟多一次DLL 调用应该也有不小的关系,为什么不把 NHibernate.JetDriver合并进主模块呢?打开 NHibernate 的源代码,试着编译了一下,报错,说是签名失败,缺少一个sn文件。后来找到这个文件是需要自己生成的,使用VS 自带的一个工具 sn.exe-kNHibernate.snx 就可以了,把这个文件放到src 目录下,编译通过。在 NHibernate 的项目里添加目录 JetDriver,然后把 NHibernate-Contrib里面的 10 目录里面的源代码一个个添加进来,编 译,通过了。试着调用一下,用昨天那个程序,重新添加引用,成功了,减少了一个DLL 文件。顺便研究了一下 JetDriver 的源代码,在 JetDialect.cs 文件里找到了一段:public override char CloseQuoteget return;初 步以为这个应该是自动添加在字段名上的修饰,于是把中间改成中括号,结果失败,查看了一下 NHibernate 输出的 SQL,没有起作用,放弃。在 JetDbCommand.cs文件里找到一段 CheckParameters,如果字段属性是日期时间字段,那么会自动转换成字符串。既然如此,为什么 我插入日期时间字段的时候还是有问题呢?它的ToString 是有格式的,ToString(dd-MMM-yyyy HH:mm:ss),把这个格式添加到我自己的程序的转换过程里,结果也失败了,原来如此,这个转换后的格式再往Access 里面写的时候没有办法正确 的转换回去了,于是修改这个格式,ToString(dd/MM/yyyy HH:mm:ss),重新编译NHibernate.dll,重新编译测试程序,把字段属性和映射属性都改成日期,成功了。至于 Password 字段名字冲 突的问题,虽然让数据库里面的字段不要叫Password 可以解决问题,但是毕竟比较丑陋,结果试了一下在映射文件里面的column 属性里加上中括号修 饰,也通过了,OK,问题不完美解决。如果想要的话,可以在映射文件的所有字段名上加上中括号,当然,其实只有 Username 和 Password 是必须 的。还是没有找到程序中哪里可以修改,自动为字段名添加修饰,难道没有考虑到这个功能?经过两天的苦战,得出一个结论,NHibernate 不适合 Access 开发,还是放弃吧。前面很容易的搞定了 Driver 的问题以后,自以为离成功已经很近了,但是没有想到,真正的困难还在后面。通 常数据库程序中最常用的一个关系就是一对多的关系,这也是 NHibernate 推荐使用的关系类型,于是很简单的建了一个数据库,一个Groups 表,包 括 GroupID 和 GroupName,一个 Items 表,包括ItemID 和 ItemName 还有 GroupID。通常这个关系可以代表数据库系统中绝 大部分关系类型。比如用户和组,产品和类别,等等。按照上一次写的 Config 文件和 hbm.xml 文件,很快写好了整个系统的框架,不过 对于一对多的关系如何处理还没有思路,看了看别人的文章,都是一个set 做 One-to-more,另一个做 More-to-one,在 Group 类里定 义了一个 Items 的变量,变量类型一开始使用IDictionary,在 Item 类里定义了一个 Group 类型的变量,代表它所对应的 Group,(一 开始定义成了 Int 型的 GroupID,后来发现这是个严重的错误,总是提示无法转换成正确的类型)。结果单独创建了一个Group 变量再保存的时候都一 直报错,说数据类型转换错误,后来查了一些英文资料,好像在C#里没有办法把IDictionary转换成NHibernate使用的Set类型,要用 ICollection,但是把 Items 改成这个类型以后,发现这个类型本身没有Add方法,那怎么把它的 Item 加进来呢?百思不得其解啊。似乎没有 一篇文章提到这个解决方案。晚上再努力查找,终于看到一丝线索,NHibernate 内部使用的是 Iesi.Collections.ISet接口类型,它派生出了好几种类型,对应不同功能的列表。ISet 这个东西 C#本身是不具备的,这是这个第三方 库模仿 Java 做出来的。于是在 Group 里面加上这个引用,然后把 Items改成这个类型,哇,终于通过了,可以添加Group 了。开心。接下来 Load 一个 Group 出来,创建一个Item,把这个Group 变量赋给 Item 的 Group 属性。保存 Item,成功了!但 是看来看去总觉得不是个味,好像那个一对多关系白定义了。因为看人家的说法,应该是定义一个 Group,然后定义一个Item,把这个Item 添加到 Group 的 Items 列表里,然后只要保存 Group,那么这个 Item 也会自动保存,结果我试来试去不成功,提示一个错误,插入或更新出错,期望 1 行,结果 0 行,可能是别的用户更改或删除的数据等等。因为一开始做的是一个 Web 应用程序,结果在配置文件里设成show_sql 为 true 以后,还是没有办法看到生成的 Sql 语句,于是新建一个exe 项目,代码一样,运行一下,果然看到Sql 语句了。奇怪的是,系统生成了两条语句,一个是插入新的 Group,然后调用了一个Select identity,然后使用一个Update 语句来更新 Items 表,结果生成的Where 语句是ItemID=0。就算这个 0 是个错误,那也应该生 成 Insert 语句啊,为什么是 Update 呢?想了一下,总算是知道这个0 是什么意思了,前面的那个Select identity对于 Access 无效,没有返回那个刚刚插入的id,所以就成了 0。这个问题恐怕不是我能解决的了,没有了这个功能,使用NHibernate 还有什么意义?如果无法提取关联对象,还要自己负责维护这个关系的话,恐怕还要出现一些条件语句在系统里,那就真的不如不用了。等会试一下用 Sql Server 是不是没有这个问题,还有再试一下提取对象是否能够自动关联起来。遇到了传说中的人品问题。今 天终于搞定了 NHibernate 的一对多问题,不知道是因为它的版本升级了还是真的我的人品问题,反正按照网上看来的代码没有一个可以正确执行的。最终 发现还需要多一步操作,就是对于每个 Item 都需要一步 Session.Save,而不是像网上所说的那样只要Save(Group)就可以自动 Save Item。完整的工作流程:建立 Configuration,Load XML 文件(或者 AddAssembly),生成SessionFactory,生成 Session,生成 Transaction,新建 Group,设定属性,Session.Save(Group),(或者 Load Group),新建 Item,设定属性,特别要指定它的 Group属性,跟组对应起来,Session.Save(Item),如果有多个 Item,重复 这个过程,然后Transaction.Commit,数据就已经保存进数据库了,Session.Close。读 取的过程:前面相同,生成Session 以后(Factory.OpenSession),Groupg=(Group)Session.Load(typeof(Group),GroupID),这样就得到了这个 ID 所对应的 Group对象,它的 Items 属性里包含了所有的下级Item,目前我用的是 HashedSet 来保存的,所以可以使用 foreach(Item it in g.Items),然后就可以使用所有的it 的属性了。在 Sql Server 里调试成功以后,切换到Access 数据库,居然发现一切问题都不存在了,完全跟 Sql Server 等效,难道那个 Select identity对于 Access 也同样有效?有待查证。不过既然过了这一关,剩下的问题就都很简单了,只不过字段多一些而已。但是根据它的这个生成 对象的方式来看的话,如果有三个以上的表使用级联的一对多关系,比如一级分类,二级分类,三级分类,然后才是Item,那么在调用生成一级分类对象的时 候,它应该是会搜索所有的数据表,生成所有的级联对象的,这是个很严重的浪费,而且如果要是用在论坛里面,要想显示首页所有的板块,那么它就会同时在数据 库里提取出所有的帖子,这个好像不太现实,继续研究中1.测试了两级一对多的关系,写入数据的确变的相当方便了,省却了大量重复的 SQL 代码的工作。但是当使用 Session.Load 加一个父对象的时候,它的子对象,以及这个子对象的所有子对象都会被加载,对于数据库或者网络都是个问题。解 决方案:给这个一对多的关系在配置文件hbm.xml 的 set 段加上一个属性,lazy=true,这样就变成延迟载入,调入父对象的时候不会自动加 载它的子集,只有当你要使用这个子集的时候(foreach),才会及时生成这个子集,这样就避免了浪费无用的查询时间。但是这样有一个要求,就是 session 必须保持活动,不能被 Close,否则就无法再去调入新的查询内容了。2.调入父对象的时候,子对象自动调入,如果用 foreach 来查询子对象,那么输出的顺序是不固定的,无论在父类中使用ListSet 还是 HashedSet,结果都是不固定的。解 决方案:还没有看到真正解决这个问题的方法,只能手动加载子类,使用Session.Find加 HQL 语言,可以达到任意控制权限。在一篇文章里看到使用 list 代替 set,然后在list的里面可以添加一个 index 属性,标明排序的字段,实体类里面使用IList,但是我没有成功。回头再试。3.在使用级联删除的时候,加载一个 Group,Session.Delete(Group),然后查看执行的 Sql语句,在Items表里居然每一行 Item执行了一次Delete,也就是说它是按照Where ItemID=?来删除的,这样 1000 条记录就执行了 1000 次,为什么不使用 Where GroupID=?呢,只要一句就搞定了,而且对于这种删除,数据库本身一般都是做了优化的。4.突然想不起来了,占位,想起来再补。NHibernateNHibernate 链接链接 accessaccess 数据库的配置文件数据库的配置文件NHibernate 链接 access 数据库的配置文件:官方没有提供链接 access 数据的专门的类,建议使用NHibernate.Dialect.SybaseDialect。它可以兼容对 access 数据库的操作。方法:在 app.config 文件中配置如下信息:NHibernate.Dialect.SybaseDialect NHibernate.Connection.DriverConnectionProvider NHibernate.Driver.OleDbDriver Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|WorkPlatform.mdb ReadCommitted 这样就完成了配置信息。使用使用 NHIBERNATENHIBERNATE过程中遇到一些问题的过程中遇到一些问题的解决方法收集解决方法收集在生成实体类的时候,有时候一些表是不需要自增列的,那么需要在对应的 XML 配置文件中设置如下:无自增列:有自增列:!-ACCESS 中插入数据后获取自增列的值需在NHIBERNATE.XML 中加入下面的设置:on_close我的我的 nhibernatenhibernate 多数据库共存配置文件多数据库共存配置文件 作者作者:8face:8facems sql:NHibernate.Connection.DriverConnectionProviderNHibernate.Driver.SqlClientDriverDataSource=DX;InitialCatalog=DaERPYinLou;User ID=sa;Password=;Trusted_Connection=FalsetrueNHibernate.Dialect.MsSql2000Dialecttruetrue 1,false 0,yes Y,no N900TOP2008-12-28 12:25|只看楼主 树型|收藏|小 中 大 2#access:NHibernate.Connection.DriverConnectionProviderNHibernate.JetDriver.JetDriver,NHibernate.JetDriverNHibernate.JetDriver.JetDialect,NHibernate.JetDriverProvider=Microsoft.Jet.OLEDB.4.0;DataSource=#db1.mdbtruetruetrue 1,false 0,yes Y,no N900注意:对于 access 的问题不是百分百解决!注意看官方文档!楼下转载的官方文档在 access节有这方面的说明!对 access 的配置,网上问的很多,还提供另一种配置方式和方言的配置方式注意:由于nhibernate2.0.1GA 的组件包中并没有配置 JetDriver,所以,如果应用 Access 就不能应用上面的配置了,可以应用下面的配置!TOP2008-12-28 12:49|只看楼主 树型|收藏|小 中 大 3#sqlitesqlite 配置配置NHibernate.Driver.SQLite20DriverNHibernate.Dialect.SQLiteDialectDataSource=|DataDirectory|#DataBase.db3;Version=3NHibernate.Connection.DriverConnectionProvidertruetruetrue 1,false 0,yes Y,no N900