使用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)

 

你可能感兴趣的:(convention)