標籤:
運用Mapping-By-Code
我們先定義一個非常簡單的Domain模型,一個int類型的Id屬性和一個string類型的Something屬性,用來代碼映射:
public class MyClass{ public int Id { get; set; } public string Something { get; set; }}1.基本映射
ModelMapper提供一種基本映射方式:使用Class方法對實體類MyClass特定映射:
- 屬性Id映射為資料庫主鍵,對應的列名稱為MyClassId、主鍵建置原則是HighLow策略。
- 屬性Something映射為資料庫普通欄位,其長度為150。
最後調用CompileMappingForAllExplicitAddedEntities方法顯式所有映射的實體(這裡是MyClass)編譯為HbmMapping對象並輸出,也可以使用CompileMappingFor方法指定實體類型。
[Test]public void BasicMappingRegistration(){ var mapper = new ModelMapper(); mapper.Class<MyClass>(cm => { cm.Id(myclass => myclass.Id, map => { map.Column("MyClassId"); map.Generator(Generators.HighLow); }); cm.Property(myclass => myclass.Something, map => map.Length(150)); }); var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); //var hbmMapping = mapper.CompileMappingFor(new[] {typeof (MyClass)}); hbmMapping.ShowInConsole();}
NHibernate對於代碼映射提供很強的靈活性,你可以像你希望的那樣隨意去組織映射:例如class-by-class方式、不同的映射點在不同的地方等等。
例如下面代碼映射,分開去配置映射,NHibernate對重複的屬性不重複映射,去合并映射:
[Test]public void WhenDuplicatePropertiesDoesNotDuplicateMapping(){ var mapper = new ModelMapper(); mapper.Class<MyClass>(cm => { cm.Id(myclass => myclass.Id, map => map.Column("MyClassId")); cm.Id(myclass => myclass.Id, map => map.Generator(Generators.HighLow)); cm.Property(myclass => myclass.Something); cm.Property(myclass => myclass.Something, map => map.Length(150)); }); var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); hbmMapping.ShowInConsole();}
你甚至也可以在兩個不同地方去映射整個實體類:
[Test]public void WhenDuplicateClassDoesNotDuplicateMapping(){ var mapper = new ModelMapper(); mapper.Class<MyClass>(cm => { cm.Id(myclass => myclass.Id, map => map.Generator(Generators.HighLow)); cm.Property(myclass => myclass.Something); }); mapper.Class<MyClass>(cm => { cm.Id(myclass => myclass.Id, map => map.Column("MyClassId")); cm.Property(myclass => myclass.Something, map => map.Length(150)); }); var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); hbmMapping.ShowInConsole();}2.Conformist映射
ModelMapper提供另外一種Conformist映射方式:class-by-class方式,即每個類定義一個類去映射,然後調用AddMapping方法把映射加入ModelMapper對象。
private class MyClassMap : ClassMapping<MyClass>{ public MyClassMap() { Id(myclass => myclass.Id, map => { map.Column("MyClassId"); map.Generator(Generators.HighLow); }); Property(myclass => myclass.Something, map => map.Length(150)); }}[Test]public void ConformistMappingRegistration(){ var mapper = new ModelMapper(); mapper.AddMapping<MyClassMap>(); var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); hbmMapping.ShowInConsole();}
上面的映射如果查看其輸出結果,都是一樣:
3.約定
ModelMapper提供了很多事件監聽器,可以通過它擴充ModelMapper。其中就是自訂約定。其實上面定義的映射從設計思想上面說也是一種約定,暫時可以稱作特定約定(Specific-Convetions)。
以Before開頭的事件監聽稱作前置約定(Pre-Conventions)。從人性化角度看前置約定(Pre-Conventions)比較民主(democratic),我們映射時可以使用特定約定(Specific-Convetions)。
以After開頭的事件監聽稱作後置約定(Post-Conventions)或者稱作Hard-Conventions。從人性化角度看後置約定(Post-Conventions)就比較共和(republican),不管前面怎麼特定,到最後一律使用後置約定(Post-Conventions)所規定的"條約"。
例如下面例子使用前置約定(Pre-Conventions):
[Test]public void MapClassWithConventions(){ var mapper = new ModelMapper(); //option:Pre-Conventions mapper.BeforeMapClass += (mi, t, map) => map.Id(x => x.Column((t.Name + "id").ToUpper())); mapper.BeforeMapProperty += (mi, propertyPath, map) => map.Column(propertyPath.ToColumnName().ToUpper()); mapper.Class<MyClass>(cm => { cm.Id(myclass => myclass.Id, map => map.Generator(Generators.HighLow)); cm.Property(myclass => myclass.Something); }); var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); hbmMapping.ShowInConsole();}
使用後置約定(Post-Conventions):
[Test]public void MapClassWithHardConventions(){ var mapper = new ModelMapper(); //option:Hard-Conventions mapper.AfterMapClass += (mi, t, map) => map.Id(x => x.Column((t.Name + "id").ToUpper())); mapper.AfterMapProperty += (mi, propertyPath, map) => map.Column(propertyPath.ToColumnName().ToUpper()); mapper.Class<MyClass>(cm => { cm.Id(myclass => myclass.Id, map => { map.Column("MyClassId"); map.Generator(Generators.HighLow); }); cm.Property(myclass => myclass.Something, map => map.Column("Whatever")); }); var hbmMapping = mapper.CompileMappingForAllExplicitAddedEntities(); hbmMapping.ShowInConsole();}
這個例子最終主鍵的映射的列名稱為MYCLASSID,Something映射的列名稱為SOMETHING。但是其思想有些不同。
結語
NHibernate3.2新增的Mapping-By-Code(代碼映射),這篇文章結合上篇的原理從整體大運用Mapping-By-Code(代碼映射)功能,有個整體方向。
著作權聲明:本文為博主http://www.zuiniusn.com 原創文章,未經博主允許不得轉載。
NHibernate剖析:Mapping篇之Mapping-By-Code(2):運用ModelMapper