【IT168技术文档】
NHibernate 为了优化性能, 提供了自己的 custom collection(ie. bag, set ...)。当我们定义一个one-many mapping 的时候, 应当在父类里面定义IList<child> children; 这样的一个集合(NH1.2 里面的所有集合类都实现 IList 接口 )。然而NHibernate自身提供的集合并没有implement IBindingList<T> , 也就是说如果我们使用NHibernate将无法实现.net 2.0 里面的complex databinding。 我想这点是NHibernate团队把 Hibernate照原样搬到.net 里来的时候所没有想到的,因为java里面没有databinding这个东东。
怎么办呢?这问题困惑了我很久,看来只能从新写一个集合类来实现数据绑定了(实现IBindingList<T> 的NHibernate 自定义集合类)。看起来还是蛮吓人的,就为了这个数据绑定写一个集合类。还好我比较聪明,去网上找了一下看看有没有相关的资料, 找到了这个好东东: NHibernate.Databinding
这是一个开源的NHibernate 扩展dll,专门为了支持complex binding做的。
具体使用方法,
1. 先吧NHibernate.Databinding.Dll 添加到项目中。
2. 把原有的集合类(bag) 替换成 BindingSet。
3. 使用 BindingSet.GetInstance<T>() generic方法生成BindingSet的实例 (不知道为什么不用constructor, 这里应该不会是用了singleton pattern呀,奇怪)
4. 在hbm 映像文件里面使用set 集合来指定BindingSet这个集合的类型。
5. 在hbm 文件里面指定使用 NHibernate.Databinding.dll 里面定义的accessor (当你存取你的object的时候,此accessor类被NHibernate 用来通过反射的途径从你的object的member variable 或者property中取值或者赋值,详细可以看Hibernate文档中hbm映像文件里 对access attribute的说明。)
贴一段我写的代码:
Hibernate Mapping:private BindingSet<Plot> plots = BindingSet.GetInstance<Plot>(); public BindingSet<Plot> Plots { get { return plots; } }
由于NHibernate.Databinding.BindingSet 这个类实现了 IBindingList<T> 接口,而此接口定义了ListChange事件,自此我们可以把他用来实现complex binding了!<set name="Plots" cascade="all" lazy="true" inverse="true" access="NHibernate.DataBinding.BindingAccessor+CamelCase, NHibernate.DataBinding"> <key column="PVAuto" /> <one-to-many class="RWeb6.BO.FormationPressure.Plot, RWeb6.BO.FormationPressure" /> </set>