wsky's blog,Record my technical life

just coding

导航

Castle实践笔记以及关于使用ActiveRecord时的集合类映射问题

     近期在项目中使用Castle ActiveRecord(以下简称AR)以及它的IOC容器,对于AR,总的来说使用起来的感觉还是蛮易用的,因为没有系统学习过Nhibernare,所以对它的底层没有太多体会,使用的时候还是得比较谨慎的;

     在开发过程中,最头痛的就是使用AR来实现复杂的数据提取的时候,非常的束缚,虽然有Hql支持,但是在整体结构上,还是让代码显得混乱,这时候就开始试想NHibernare在这方面是如何做的,说到复杂,就必然提到关联提取,对于ORM而言,提取出来的数据是要映射到对象上的,问题就在这里,很多时候,需要提取的数据并非一个完整的预先定义的实体,要是能返回一个DataSet或者DataRow,那样不就非常方便了?查阅了一些资料,没有得到多少答案。

     暂时先不说这个理想的弥补的方式,先回到Nhibernate上来,对于AR而言,它底层是基于Nhibernate,只是一个包装型的框架,它让我们可以从大量的配置文件中解脱出来,用简易的属性来代替映射文件,但是这样也有很大的问题,首先属性是不可能完全的代替映射配置文件,自由度和可控性不如配置文件,不过Castle的观点是认为这是不需要专注的部分,应该自动的实现配置映射,总之AR只是Nhibernate的一个子集,另外就是一个更为显著的缺点,因为使用属性,使得AR的实体类不单纯,同时还给每个实体增加一个AR基类, 这样就更加限制了移植性,甚至让我考虑实现多套实体来弥补…

     已经在网上看过非常多关于ORM的讨论,性能是最为尖锐的问题,这就不说了,不管如何,ORM确实是好东西,解决OO和数据库设计不一致,对二者进行了隔离;既然使用了ORM,就要理解它的底层,最终都是要满足项目的需求,如果性能瓶颈真是出在OR上,那就不必非要选择它.

 

关于AR的一些评价参考http://www.cnblogs.com/bluewater/archive/2007/08/14/855557.html

 

随着项目的进行,使用AR的过程中越发觉得不理解底层所封装的Nhibernate,是很难驾驭好它的,先来看看Nhibernate文档中对于持久化集合类的说明:

以下为原文档引用:

NHibernate可以持久化以下集合的实例,

包括System.Collections.IDictionary,System.Collections.IList, Iesi.Collections.ISet和任何持久实体或值的数组。类型为System.Collections.ILst的属性还可以使用"bag"语义来持久。

警告:用于持久化的集合,除了集合接口外,不能保留任何实现这些接口的类所附加的语义(例如:Iesi.Collections.ListSet带来的迭代顺序iteration order)。所有的持久化集合,实际上都各自按照System.Collections.Hashtable, System.Collections.ArrayList, Iesi.Collections.HashedSet的语义直接工作。更深入地说,对于一个包含集合的属性来说,必须把.NET类型定义为接口(也就是IDictionary, IList或者ISet)。存在这个限制的原因是,在你不知道的时候,NHibernate暗中把你的IDictionary, IList 和 ISet 的实例替换成了它自己的关于这些集合的实现。(所以在你的程序中,谨慎使用==操作符。)

集合遵从对值类型的通常规则:不能共享引用, 与其包含的实体共存亡。由于存在底层的关联模型,集合不支持空值语义;并且NHibernate不会区分一个null的集合引用和一个不存在元素的空集合。

集合类在被一个持久化对象引用的时候,会自动持久化,当不再被引用时将会自动删除。如果一个集合被从一个持久化对象传递到另一个,它的元素可能会从一个表转移到另一个表。你应该不需要对此特别关心。就如同你使用普通的 .NET集合类一样使用NHibernate的集合类,但是你需要确信使用前你理解了双向关联的语义(后面会讨论)。

     集合实例在数据库中根据指向对应实体的外键而得到区别。这个外键被称为集合的关键字。在NHibernate配置文件中使用 <key> 元素来映射这个集合的关键字。

     集合类可以产生多种映射,涵盖了很多常用的关系模型,值集合,多对多关联,一对多关联,等等,具体可以参考Nhibernate官方文档的集合类映射章节,这里要说的是AR中,因为是对Nhbernate的包装,所以它依然要使用以上所提到的三个集合类型,IList集合则是AR中普遍提供的返回集合类型,对于IList,.net中的可索引的集合的抽象基类,在用代码生成工具生成的AR实体中可以看到关联集合的属性是IList类型,NHibernate不支持带有索引的集合(IList,IDictionary或者数组)作为"多"的那一端的双向one-to-many关联,你必须使用集合或者bag映射。

     AR在处理这种关联的时候,使用bag映射,PersistentBag,返回Ilist集合,根据上面引用文档中提到的,关联的Ilist集合是依赖于Session和实体关联,当实体消亡,Ilist也就无法使用了,所以当我们在Lazy模式下试图利用实体中的关联来取得这个集合的时候,会失败报错”No Session”,除非我们在代码里先取得了这个实体,在Session存在的情况在才可以获得关联的集合,这就是问题,很自然的关联却无法在底层封装好来使用,不得不在业务层使用的时候反复的使用using(new SessionScope()){… }来进行Lazy方式的提取,而同样的返回Ilist的方法,比如FindAll(),取得所有实体,则是可行的,这里没有理解Nhibernate对于集合类的映射方式,那我们就会非常的不解,AR将这些配置都隐藏了,而我们不了解Nhibernate,于是我们很困惑AR关联特性的使用,为了更好的使用AR,我们还是得先学习了解Nhibernate,对于集合类的使用以及关联,需要了解基本的持久化集合,关联实现,延迟等以及了解一些一级,二级缓存的概念。

 

Nibernate入门文章参考http://www.cnblogs.com/bluewater/archive/2007/08/14/855547.html

最好的就是先阅读官方文档,有详细说明(^^阅读中,收获不小)

 

以上对AR使用以及理解一些Nbinernate的映射做一些笔记,多为个人理解,请多多指正;不断学习中。

posted on 2008-04-14 01:17  wsky  阅读(518)  评论(0编辑  收藏  举报