您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關使用c# 怎么編寫一個ORM框架,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
ORM全稱 Object Relational Mapping,翻譯過來就是對象關系映射。是一種通過描述對象與數據庫之間映射關系的數據,將對象保存到數據庫中的技術。
在C#中,曾經Entity Framework光芒萬丈,遮蓋了其他ORM框架的光輝(甚至如今都是如此)。
后來慢慢涌現除了其他的一些ORM框架,進一步豐富了市場。所以現有比較流行的大概有以下幾種:
Dapper 一個輕量的ORM框架
Entity Framework/Entity Framework Core 功能完備的框架
Nhibernate Java平臺上著名的Hibernate的.net版
等等
嗯,這是我最近找到的創作組還在更新的幾個框架,當然還有其他的很多有趣好用的ORM框架。歡迎各位補充哈。
這一篇的主要目的不是介紹這些框架(這是以后的內容),而是通過我們自己實現一個類ORM框架來了解底層核心。
我們先分析一下,如果我們設計一個實體對象與數據庫之間轉換的工具類應該具有哪些功能?
一個屬性與數據庫字段的映射關系
增刪改查的SQL模板
查詢結果與對象的轉換
首先,聲明一個類,因為不能僅支持一種類型,所以這個類的所有與數據庫有關的方法都是泛型方法,或者這個類是泛型類,所以定義為泛型類:
public class OrmUtil<T> { }
我們事先約定類名即表名,屬性名即表的列名,所以我們可以快速得到以下內容:
/// <summary> /// T的類型實例 /// </summary> private Type dType; /// <summary> /// T的屬性表 /// </summary> private PropertyInfo[] properties; public OrmUtil() { dType = typeof(T); properties = dType.GetProperties(); }
聲明一個數據庫連接:
public SqlConnection Connection { get; set; }
創建一個私有方法,檢查連接是否可用:
/// <summary> /// 檢查連接是否可用 /// </summary> /// <returns></returns> private bool CheckConnection() { return Connection?.State == ConnectionState.Open; }
準備工作完成,然后開始編寫具體的業務方法:
Insert:
public int Insert(T entity) { if (!CheckConnection()) return -1;// 檢查狀態 var insert = $"insert into {dType.Name}({string.Join(",", properties.Select(t => t.Name))})"; var values = properties.Select(p => p.GetValue(entity)); var commandText = $"{insert} values('{string.Join("','", values)}')"; var command = Connection.CreateCommand(); command.CommandText = commandText; var result = command.ExecuteNonQuery(); return result; }
首先按照屬性名與列名之間的映射拼接 SQL,然后執行SQL命令。
Update:
public int Update(T entity,string keyName,object keyValue) { if (!CheckConnection()) return -1; var setValues = properties.ToDictionary(p => p.Name, p => $"'{p.GetValue(entity)}'"); var setSql = string.Join(",", setValues.Select(pair=>$"{pair.Key}='{pair.Value}'")); var sql = $"update {dType.Name} set {setSql} where {keyName} = '{keyValue}'"; var command = Connection.CreateCommand(); command.CommandText = sql; return command.ExecuteNonQuery(); }
Update需要注意的就是如何正確拼接賦值sql。
Delete:
刪除滿足條件的對象:
public int Delete(T entity) { if (!CheckConnection()) return -1; var querySet = properties.Select(p => $"{p.Name} = '{p.GetValue(entity)}'"); var sql = $"delete from {dType.Name} where {string.Join(" and ", querySet)}"; var command = Connection.CreateCommand(); command.CommandText = sql; return command.ExecuteNonQuery(); }
這里寫法有時候根據實際業務不同,大多數情況下刪除主鍵對應的元素,或者滿足某一個條件的所有元素。這里只是做了個演示,小伙伴們可以試試自己改造一下。
Search:
先創建一個從DataTable轉成對象的工具方法:
private List<T> Convert(DataTable table) { var list = new List<T>(table.Rows.Count);//事先聲明一下容量 foreach(DataRow row in table.AsEnumerable()) { T entity = Activator.CreateInstance<T>(); foreach(var p in properties) { if (!table.Columns.Contains(p.Name)) continue;// 如果屬性名不在表格中,則忽略 p.SetValue(entity, row[p.Name]); } list.Add(entity); } return list; }
好,我們寫一個查詢方法:
public List<T> SearchAll() { var adapter = new SqlDataAdapter($"select * from {dType.Name}", Connection); var set = new DataSet(); adapter.Fill(set); return Convert(set.Tables[0]); }
這樣一個簡單的ORM框架就這樣形成雛形了,當然實際上的ORM底層比這復雜,因為需要支持不同的數據庫,所以Connection 就不能簡簡單單的是一個SqlConnection了,或者底層不是像我們一樣取巧使用DataTable了。
實際上的DataTable到類對象的轉換要比我寫的復雜一點,因為還要判斷這個屬性是否是可讀、可寫的。
看完上述內容,你們對使用c# 怎么編寫一個ORM框架有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。