上文講述了數據庫上下文,接下來就是數據庫中的表與實體類的關聯了(映射)。app
先看下我DEMO中的上下文與表實體的關聯:框架
1 namespace Demo.PO 2 { 3 4 public class Table : DbContext<Table> 5 { 6 [Set(Name = "Members_User")] 7 public TableSet<UserVO> User { get; set; } 8 9 [Set(Name = "Members_Role")] 10 public TableSet<UserRoleVO> UserRole { get; set; } 11 } 12 }
TableSet表操做類:針對數據庫表提供的一系列CURD的操做。被TableSet包含的就是表字段了。函數
一、表實體類:工具
1 public class UserVO : IEntity<int?> 2 { 3 /// <summary> 用戶ID </summary> 4 [Field(IsPrimaryKey = true)] 5 public int? ID { get; set; } 6 /// <summary> 用戶名 </summary> 7 [Field()] 8 public string UserName { get; set; } 9 /// <summary> 密碼 </summary> 10 public string PassWord { get; set; } 11 /// <summary> 會員類型 </summary> 12 public eumGenderType? GenderType { get; set; } 13 /// <summary> 登錄次數 </summary> 14 public int? LoginCount { get; set; } 15 /// <summary> 登錄IP </summary> 16 public string LoginIP { get; set; } 17 /// <summary> 登錄IP </summary> 18 [Field(Name = "getdate()")] 19 public DateTime? GetDate { get; set; } 20 /// <summary> 建立時間 </summary> 21 public DateTime? CreateAt { get; set; } 22 }
能夠看到,咱們具體的實體,實際上是一個POCO的實體。this
沒錯,在V1.x中,框架的一個改變也是爲了減輕實體的」負擔「,也讓框架更加輕量級,而不是侵入式的。spa
這裏重點說下:[Field(Name = "getdate()")].net
在後面咱們會講到Field.Name 是顯示的告訴框架這個類屬性綁定數據庫中對應的表字段名稱。
熟悉MSSQL朋友知道,getdate()並非字段名稱,則是MSSQL提供的函數。框架對此也是支持的。
舉個例子,表有兩個字段,A、B 都是int類型,
咱們用SQL對A、B的值相加後進行排序是很容易實現的。
而經過框架,咱們能夠定義一個類屬性,而後Field.Name = "A+B" ,這樣咱們在排序時,就按照普通的字段進行Desc(o=>o.變量)就能夠了。
另外這裏繼承了IEntity,如前面文章說到的,是爲了支持提供的擴展。咱們看看IEntity的接口代碼吧:
1 namespace FS.Core.Infrastructure 2 { 3 /// <summary> 經過實體類的繼承後,後續Set、擴展方法提供針對主鍵的Where條件 </summary> 4 /// <typeparam name="T"></typeparam> 5 public interface IEntity<T> 6 { 7 /// <summary> 主鍵ID </summary> 8 T ID { get; set; } 9 } 10 11 /// <summary> 經過實體類的繼承後,後續Set、擴展方法提供針對主鍵的Where條件(默認爲int?) </summary> 12 public interface IEntity : IEntity<int?> { } 13 }
接口只有一個屬性:ID,大部份,咱們的表都有一個主鍵。這個主鍵是自動標識的。
繼承它後,框架提供了一Where條件自動轉換的支持:
/// <summary> /// 獲取下一條記錄 /// </summary> /// <param name="ID">當前ID</param> /// <param name="ts">TableSet</param> /// <typeparam name="TEntity">實體類</typeparam> public static TEntity ToNextEntity<TEntity>(this TableSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new() { return ts.Where(o => o.ID > ID).Asc(o => o.ID).ToEntity(); } /// <summary> /// 獲取上一條記錄 /// </summary> /// <param name="ID">當前ID</param> /// <param name="ts">TableSet</param> /// <typeparam name="TEntity">實體類</typeparam> public static TEntity ToPreviousEntity<TEntity>(this TableSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new() { return ts.Where(o => o.ID < ID).Desc(o => o.ID).ToEntity(); } /// <summary> /// 獲取下一條記錄 /// </summary> /// <param name="ID">當前ID</param> /// <param name="ts">TableSet</param> /// <typeparam name="TEntity">實體類</typeparam> public static TEntity ToNextEntity<TEntity>(this ViewSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new() { return ts.Where(o => o.ID > ID).Asc(o => o.ID).ToEntity(); } /// <summary> /// 獲取上一條記錄 /// </summary> /// <param name="ID">當前ID</param> /// <param name="ts">TableSet</param> /// <typeparam name="TEntity">實體類</typeparam> public static TEntity ToPreviousEntity<TEntity>(this ViewSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new() { return ts.Where(o => o.ID < ID).Desc(o => o.ID).ToEntity(); }
固然這裏沒辦法貼出全部的擴展方法來,但讓你們知道它的目的就是讓咱們常常操做的:o.ID == x 、o=> IDs.Contains(o.ID) 這些操做變的更加方便,不須要手動敲代碼完成。
以上代碼在Demo中。你們能夠直接在源代碼裏面去查找
二、咱們先來介紹第一個特性:字段的映射
[FieldAttribute]特性目的是告訴框架,當前的這個類屬性與數據庫的表字段是如何關聯在一塊兒的。好比顯式的指定表字段的名稱。
咱們先來看下面的表格:
序號 | 變量 | 註釋 | 類型 | 適用範圍 | 說明 |
1 | Name | 數據庫字段名稱 | string | 所有 | 指定表字段、視圖字段名稱、存儲過程參數的名稱、數據庫函數 未顯示指定時,默認使用當前的類屬性名稱做爲缺省名稱 |
2 | IsPrimaryKey | 是否爲數據庫主鍵 | bool | TableSet | 默認:false 設爲:true 而且該變量賦了值是:Insert操做,在MSSQL裏,會啓用SET IDENTITY_INSERT設置,在Update時,會轉換成條件,並去掉賦值。 好比:Table.Data.User.Update(new User{ ID=1,Name="xxx")); 會被轉換成:Table.Data.User.Where(o=>o.ID == 1).Update(new User{ Name="xxx")); |
3 | InsertStatusType | 插入時字段狀態 | StatusType 枚舉類型 |
TableSet | 默認:CanWrite 設爲:ReadOnly時,在對應的插入或者更新時,該賦值會被過濾掉(忽略) 設爲:ReadCondition時,在對應的插入或者更新時,該賦值會被轉換成 == 條件。同時過濾掉賦值(忽略) 這個特性運用的好,對咱們編寫代碼時,能夠省去不少Where(o=>o.ID == 1)這種寫法,以及安全保護。(禁止被更新,即時賦了值) |
4 | UpdateStatusType | 修改時字段狀態 | TableSet | ||
5 | IsMap | 是否映射到數據庫字段中 | bool | 所有 | 默認:true 設爲:false 將不映射數據庫 |
這是在咱們類屬性(字段中)申明的。
三、第2個經常使用特性:指定表名、視圖名、存儲過程名稱
目前只有一個Name屬性。
序號 | 變量 | 註釋 | 類型 | 適用範圍 | 說明 |
1 | Name | 表名稱、視圖名稱、存儲過程名稱 | string | 所有 | 指定表、視圖、存儲過程的名稱 未顯示指定時,默認使用當前的類名稱做爲缺省名稱 |
它是在上下文中的Set屬性上申明的特性。能夠參考上面出現的:Table類。
相信經過上文的說明,你們知道如何進行數據庫的映射了。
今天這篇與昨天的,都是環境搭建過程而已。
到了下一篇,就開始講解實質性的數據庫操做了。但願給你們帶來驚喜!
QQ羣:116228666 (Farseer.net開源框架交流) 請註明:Farseer.Net
Farseer.Net是一款ORM框架 + 經常使用工具 + 擴展集合。
Farseer 寓意:先知、預言家 一般在某些場合時,提供計謀、策略。也但願該框架能給你們提供最大化的便捷。
ORM:其英文全稱是:Object(對象) Relational(關係) Mapping(映射)
Farseer.Net的目標是:快速上手、快速開發、簡單方便。
1 Table.Data.User.Where(o=>o.ID == 1).ToEntity(); 2 Table.Data.User.Where(o=>o.ID > 1).ToList(); 3 Table.Data.User.Where(o=>o.ID != 0).Delete(); 4 Table.Data.User.Where(o=>o.ID != 0).AddUp(o=>o.LoginCount, 1); 5 Table.Data.User.Where(o=>o.ID == 1).Update(new User{ UserName = "newName" }); 6 Table.Data.User.Insert(new User{ UserName = "newName" });