使用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 : ModelMapper2: {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 : LocalSessionFactoryObject2: {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 TableName11: {12: get { return typeof (TEntity).Name + "s"; }//todo13: }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)