在Farseer.Net 中 ORM的核心在命名空間:FS.ORM 。app
目前只有4個類文件。其實這4個文件只要是用來作數據庫與實體模型之間的映射關係及緩存。至於SQL生成、不一樣數據庫的驅動支持等 在另外的命名空間:FS.Core 中。框架
對於ORM來講,咱們在轉換成數據庫操做前,是先讓Farseer.Net能「讀懂」實體與數據庫之間的關係,才能作出對應的SQL生成操做。在本框架中,實際都是最終生成SQL。交由ADO.NET來完成執行數據庫操做的。函數
Mapping.cs :映射的核心文件,都是經過該類,來完成對實體與數據庫之間的映射過程。工具
ModelCache.cs :映射緩存,導致咱們不須要對實體進行重複的反射操做。將會在第一次映射後緩存起來。性能
DBAttribute.cs :顧名思義,是數據庫的特性。好比前面咱們看到在實體類名稱的特徵:[DB(Name="xxx表名稱",DbIndex = 1)]學習
ModelAttribute.cs :這個是屬性字段的映射,包括字段的名稱、中文名稱、必填、長度、自增列等。spa
這個對象將會對實體類的表信息、字段信息(多個)進行全面解析。
1 /// <summary> 2 /// ORM 映射關係 3 /// </summary> 4 public class Mapping 5 { 6 /// <summary> 7 /// 獲取全部屬性 8 /// </summary> 9 public readonly Dictionary<PropertyInfo, ModelAttribute> ModelList; 10 11 /// <summary> 12 /// 關係映射 13 /// </summary> 14 /// <param name="type">實體類Type</param> 15 internal Mapping(Type type) 16 17 /// <summary> 18 /// 類屬性 19 /// </summary> 20 public DBAttribute ClassInfo { get; set; } 21 22 /// <summary> 23 /// 自增ID 24 /// </summary> 25 public string IndexName { get; set; } 26 27 /// <summary> 28 /// 類型 29 /// </summary> 30 public Type Type { get; set; } 31 32 /// <summary> 33 /// 經過實體類型,返回Mapping 34 /// </summary> 35 public static implicit operator Mapping(Type type) 36 37 /// <summary> 38 /// 獲取當前屬性(經過使用的propertyName) 39 /// </summary> 40 /// <param name="propertyName">屬性名稱</param> 41 public KeyValuePair<PropertyInfo, ModelAttribute> GetModelInfo(string propertyName = "") 42 43 /// <summary> 44 /// 獲取標註的名稱 45 /// </summary> 46 /// <param name="propertyInfo">屬性變量</param> 47 /// <returns></returns> 48 public string GetUserName(PropertyInfo propertyInfo) 49 }
Mapping的構造函數傳入的是實體類的Type。而後對這個類進行 《類特性》、《屬性特性》的轉化。同時由於這裏涉及到數據庫類型及訪問方式了,因此Db.Config若是不存在,則會建立這份配置文件出來。
同時加入對數據驗證的錯誤提示:
1 // 字符串長度判斷 2 if (modelAtt.StringLength != null && modelAtt.StringLength.ErrorMessage.IsNullOrEmpty()) 3 { 4 if (modelAtt.StringLength.MinimumLength > 0 && modelAtt.StringLength.MaximumLength > 0) 5 { 6 modelAtt.StringLength.ErrorMessage = string.Format("{0},長度範圍必需爲:{1} - {2} 個字符之間!", modelAtt.Display.Name, modelAtt.StringLength.MinimumLength, modelAtt.StringLength.MaximumLength); 7 } 8 else if (modelAtt.StringLength.MaximumLength > 0) 9 { 10 modelAtt.StringLength.ErrorMessage = string.Format("{0},長度不能大於{1}個字符!", modelAtt.Display.Name, modelAtt.StringLength.MaximumLength); 11 } 12 else 13 { 14 modelAtt.StringLength.ErrorMessage = string.Format("{0},長度不能小於{1}個字符!", modelAtt.Display.Name, modelAtt.StringLength.MinimumLength); 15 } 16 } 17 18 // 值的長度 19 if (modelAtt.Range != null && modelAtt.Range.ErrorMessage.IsNullOrEmpty()) 20 { 21 if (modelAtt.Range.Minimum.ConvertType(0m) > 0 && modelAtt.Range.Maximum.ConvertType(0m) > 0) 22 { 23 modelAtt.Range.ErrorMessage = string.Format("{0},的值範圍必需爲:{1} - {2} 之間!", modelAtt.Display.Name, modelAtt.Range.Minimum.ConvertType(0m), modelAtt.Range.Maximum.ConvertType(0m)); 24 } 25 else if (modelAtt.Range.Maximum.ConvertType(0m) > 0) 26 { 27 modelAtt.Range.ErrorMessage = string.Format("{0},的值不能大於{1}!", modelAtt.Display.Name, modelAtt.Range.Maximum.ConvertType(0m)); 28 } 29 else 30 { 31 modelAtt.Range.ErrorMessage = string.Format("{0},的值不能小於{1}!", modelAtt.Display.Name, modelAtt.Range.Minimum.ConvertType(0m)); 32 } 33 }
經過ModelList,咱們能夠獲取該類的全部字段信息。這對咱們在一些項目執行的過程當中須要動態的獲取類屬性的信息是頗有須要的。
GetModelInfo,經過傳入數據庫字段名稱,找到映射的類屬性。
GetFieldName,經過傳入類屬性,找到映射的數據庫字段信息。
1 namespace FS.ORM 2 { 3 /// <summary> 4 /// 緩存數據庫和實體類的映射關係 5 /// </summary> 6 public static class ModelCache 7 { 8 /// <summary> 9 /// 緩存全部實體類 10 /// </summary> 11 private static readonly Dictionary<Type, Mapping> ModelList = new Dictionary<Type, Mapping>(); 12 13 private static readonly object LockObject = new object(); 14 15 /// <summary> 16 /// 返回實體類映射的信息 17 /// </summary> 18 /// <param name="type">實體類Type</param> 19 public static Mapping GetInfo(Type type) 20 { 21 if (!ModelList.ContainsKey(type)) 22 { 23 lock (LockObject) 24 { 25 if (!ModelList.ContainsKey(type)) 26 { 27 ModelList.Add(type, new Mapping(type)); 28 } 29 } 30 } 31 32 return ModelList[type]; 33 } 34 35 /// <summary> 36 /// 清除緩存 37 /// </summary> 38 public static void ClearCache() 39 { 40 ModelList.Clear(); 41 } 42 } 43 }
ModelCache對象就是將Mapping進行緩存的操做。經過GetInfo方法,進行緩存並返回Mapping對象。
所以你們若是須要Mapping對象時,必須經過ModelCache.GetInfo的靜態方法進行獲取。不然直接操做Mapping對象,將會引起性能問題。
存儲與數據庫的類型、訪問方式,及表名稱。
1 /// <summary> 2 /// 實體類的屬性標記 3 /// </summary> 4 [AttributeUsage(AttributeTargets.Class)] 5 public sealed class DBAttribute : Attribute 6 { 7 /// <summary> 8 /// 表名 9 /// </summary> 10 public string Name { get; set; } 11 12 /// <summary> 13 /// 設置數據庫鏈接配置(Dbconfig)的索引項 14 /// </summary> 15 public int DbIndex { get; set; } 16 17 /// <summary> 18 /// 設置數據庫鏈接字符串 19 /// </summary> 20 public string ConnStr { get; set; } 21 22 /// <summary> 23 /// 設置數據庫類型 24 /// </summary> 25 public DataBaseType DataType { get; set; } 26 27 /// <summary> 28 /// 設置數據庫版本 29 /// </summary> 30 public string DataVer { get; set; } 31 32 /// <summary> 33 /// 設置數據庫執行T-SQL時間,單位秒默認是30秒 34 /// </summary> 35 public int CommandTimeout { get; set; }
這裏代碼比較少,我就不在貼上來了,你們能夠到框架中查看。大部份的特性,咱們仍是利用LINQ TO SQL的。能夠減小你們的學習成本。
主要是針對字段的必填、數據長度、數字值類型的範圍、或者正則(可自定義加入如郵件格式、手機格式的驗證)。
另外須要說明的是,默認全部字段都是映射到數據庫字段的。若是有一些額外的字段不想加入到字段中。
能夠在字段的特性申明:[NotJoinAttribute(true)],代表該類屬性不對數據庫的字段進行映射。
QQ羣:116228666 (Farseer.net開源框架交流) 請註明:Farseer.Net
Farseer.Net是一款ORM框架 + 經常使用工具 + 擴展集合。
Farseer 意爲:先知、預言家 一般在某些場合時,提供計謀、策略。也但願該框架能給你們提供最大化的便捷。
ORM:其英文全稱是:Object(對象) Relational(關係) Mapping(映射)
Farseer.Net的目標是:快速上手、快速開發、簡單方便。
1 new User { ID = 1, Name = "張三" }.Insert()