使用Spring.Net 1.3.2 + NHibernate 3.2的mapping by code和default convention

NH的官网今天出了两篇blog,讲如何使用NH3.2的mapping by code,不过都弱爆了,推荐直接看Fabio Maulo的blog去(

简单的说,NH的mapping by code有三种方式

  • 直接为每个entity类调用ModelMapper.Class方法
  • Conformist映射,也就是class by class
  • Convention,当然约定是可以被explicit mapping所覆盖的

本文展示第二三种混合的方式,也就是使用convention,然后覆盖。

 

首先,使用Convention

NH3.2中,使用Convention的方法也有两种,一种是使用前后置事件,另一种则是使用ModelInspector。后者对DI提供了更好的支持。其中NH内嵌的ConventionModelMapper就是使用了后者,看它的构造函数

  1: public class ConventionModelMapper : ModelMapper
  2: {
  3:     public ConventionModelMapper()
  4:         : base(new SimpleModelInspector())
  5:     {
  6:         AppendDefaultEvents();
  7:     }
  8: }

其实ModelMapper的构造函数有好几个重载,估计是能实现更强的自定义功能吧,我还没有尝试过。

 

然后,尝试集成进Spring.Net 1.3.2

Spring.Net这货,虽然提供了Spring.Data.NHibernate32.dll,但是其实是把基于NH2.x的代码在结合NH3.2重新build了一遍而已= =

好歹Spring提供了不错的扩展性,自己动手丰衣足食吧~~

  1:     public class Nh3LocalSessionFactoryObject : LocalSessionFactoryObject
  2:     {
  3:         public IEnumerable<IConformistHoldersProvider> Mappings { get; set; }
  4:         public IModelInspector ModelInspector { get; set; }
  5: 
  6:         protected override void PostProcessMappings(Configuration config)
  7:         {
  8:             base.PostProcessMappings(config);
  9: 
 10:             var mapper = new ModelMapper(ModelInspector);
 11:             foreach (var mapping in Mappings)
 12:             {
 13:                 mapper.AddMapping(mapping);
 14:             }
 15:             var hbmMappings = mapper.CompileMappingForEachExplicitlyAddedEntity();
 16:             foreach (var hbmMapping in hbmMappings)
 17:             {
 18:                 config.AddMapping(hbmMapping);
 19:             }
 20:         }
 21:     }

其中,IConformistHoldersProvider是ClassMapping、SubClassMapping等几个Mapping类共同实现的接口。
ModelInspector的话,我会使用SimpleModelInspector,毕竟这篇文章就是想试试default convention。

 

那么,效果如何呢?

对比EF 4.1的话,有些不同也有些差距。

例如NH3.2默认表名=类名,而EF4.1则默认表名=类名的复数。

再例如EF 4.1中,如果用int做id则默认该id是自增长的,NH3.2中则还是要写代码,我将它写在基类里。

  1:     public class EntityClassMapping<TEntity> : ClassMapping<TEntity>
  2:         where TEntity : class, IEntity<int>
  3:     {
  4:         public EntityClassMapping()
  5:         {
  6:             Id(e => e.Id, mapper => mapper.Generator(Generators.Identity));
  7:             Table(TableName);
  8:         }
  9: 
 10:         private string TableName
 11:         {
 12:             get { return typeof (TEntity).Name + "s"; }//todo
 13:         }
 14:     }

 

接下来,尝试一下覆盖default convention

例如,给一列重命名,代码如下

  1:     public class PersonMapping : EntityClassMapping<Person>
  2:     {
  3:         public PersonMapping()
  4:         {
  5:             Property(p => p.IsMale, mapping => mapping.Column("Gender"));
  6:         }
  7:     }

实话实说,我觉得这个API设计的是比较丑陋的。。。对比EF 4.1中实现相同任务的代码

  1:     public class PersonMapping : EntityMapping<Person>
  2:     {
  3:         public PersonMapping()
  4:         {
  5:             Property(p => p.IsMale).HasColumnName("Gender");
  6:         }
  7:     }

在整个NH3.2的mapping by code API中都充斥满了Action<XXXX>真是让人不胜其烦。

本文就到这里,说的实在是比较简略,不过我也一向没有写科普blog的兴致= =

更多细节还是请参考Fabio Maulo的blog。

 

[Update]出丑了,表名变复数可以使用classCustomizer.Table(Inflector.Pluralize(type.Name)

请参考这篇博文。 

classCustomizer.Table(Inflector.Pluralize(type.Name)

 

posted @ 2011-09-06 10:08 jiaxingseng 阅读(...) 评论(...) 编辑 收藏