手写ORM入门篇(一)
對象關系映射(英語:(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用于實現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換 。從效果上說,它其實是創(chuàng)建了一個可在編程語言里使用的--“虛擬對象數(shù)據(jù)庫”。
面向?qū)ο笫菑能浖こ袒驹瓌t(如耦合、聚合、封裝)的基礎上發(fā)展起來的,而關系數(shù)據(jù)庫則是從數(shù)學理論發(fā)展而來的,兩套理論存在顯著的區(qū)別。為了解決這個不匹配的現(xiàn)象,對象關系映射技術應運而生。
對象關系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化數(shù)據(jù)的方法。ORM方法論基于三個核心原則: 簡單:以最基本的形式建模數(shù)據(jù)。 傳達性:數(shù)據(jù)庫結(jié)構(gòu)被任何人都能理解的語言文檔化。 精確性:基于數(shù)據(jù)模型創(chuàng)建正確標準化的結(jié)構(gòu)。 典型地,建模者通過收集來自那些熟悉應用程序但不熟練的數(shù)據(jù)建模者的人的信息開發(fā)信息模型。建模者必須能夠用非技術企業(yè)專家可以理解的術語在概念層次上與數(shù)據(jù)結(jié)構(gòu)進行通訊。建模者也必須能以簡單的單元分析信息,對樣本數(shù)據(jù)進行處理。ORM專門被設計為改進這種聯(lián)系。
簡單的說:ORM相當于中繼數(shù)據(jù)。具體到產(chǎn)品上,例如ADO.NET Entity Framework。DLINQ中實體類的屬性[Table]就算是一種中繼數(shù)據(jù)。
BaseModel示例代碼:
1 public class BaseModel 2 { 3 /// <summary> 4 /// 所有實體的父類,非自增主鍵GUID 5 /// </summary> 6 public string Id { set; get; } 7 }User示例代碼:
1 public class User : BaseModel
2 {
3 public string Account { get; set; }
4
5 public string Password { get; set; }
6
7 public string Name { get; set; }
8
9 public int Sex { get; set; }
10
11 public int Status { get; set; }
12
13 public string BizCode { get; set; }
14
15 public DateTime CreateTime { get; set; }
16
17 public string CrateId { get; set; }
18
19 public string TypeName { get; set; }
20
21 public string TypeId { get; set; }
22
23 } IBaseDAL示例代碼:
1 public interface IBaseDAL 2 { 3 /// <summary> 4 /// 根據(jù)主鍵返回一個實體 5 /// </summary> 6 /// <typeparam name="T"></typeparam> 7 /// <param name="id"></param> 8 /// <returns></returns> 9 T Find<T>(string id) where T : BaseModel; 10 11 /// <summary> 12 /// 返回一個List<Medel>實體集合 13 /// </summary> 14 /// <typeparam name="T"></typeparam> 15 /// <returns></returns> 16 List<T> FindAll<T>() where T : BaseModel; 17 18 /// <summary> 19 /// 添加一條記錄 20 /// </summary> 21 /// <typeparam name="T"></typeparam> 22 /// <param name="t"></param> 23 /// <returns></returns> 24 bool Add<T>(T t) where T : BaseModel; 25 26 /// <summary> 27 /// 更新一個實體 28 /// </summary> 29 /// <typeparam name="T"></typeparam> 30 /// <param name="t"></param> 31 /// <returns></returns> 32 bool Update<T>(T t) where T : BaseModel; 33 34 /// <summary> 35 /// 刪除一條記錄 36 /// </summary> 37 /// <typeparam name="T"></typeparam> 38 /// <param name="t"></param> 39 /// <returns></returns> 40 bool Delete<T>(T t) where T : BaseModel; 41 }BaseDAL示例代碼
1 /// <summary> 2 /// 泛型方法添加BaseModel約束,所有實體類必須有一個非自增的主鍵Id,Id的值為隨機的GUID, 3 /// </summary> 4 public class BaseDAL : IBaseDAL 5 { 6 /// <summary> 7 /// 數(shù)據(jù)庫連接字符串 8 /// </summary> 9 private static string ConnectionString = ConfigurationManager.ConnectionStrings["OpenAuthDB"].ConnectionString; 10 11 public bool Add<T>(T t) where T : BaseModel 12 { 13 Type type = t.GetType(); 14 string columnStr = string.Join(",", type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => $"[{p.Name}]")); 15 string valueStr = string.Join(",", type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => $"@{p.Name}")); 16 var parameterList = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => new SqlParameter($"@{p.Name}", p.GetValue(t) ?? DBNull.Value)); 17 string sqlStr = $"Insert Into [{type.Name}] ({columnStr}) values ({valueStr})"; 18 using (SqlConnection conn = new SqlConnection(ConnectionString)) 19 { 20 SqlCommand command = new SqlCommand(sqlStr, conn); 21 command.Parameters.AddRange(parameterList.ToArray()); 22 conn.Open(); 23 //如果Id是自增的,在sql后面增加個 Select @@Identity; command.ExecuteScalar,新增后把Id拿出來. 24 return command.ExecuteNonQuery() > 0; 25 } 26 } 27 28 public bool Delete<T>(T t) where T : BaseModel 29 { 30 //獲取T的類型 31 Type type = typeof(T); 32 var parameter = new SqlParameter("Id", type.GetProperty("Id").GetValue(t) ?? DBNull.Value); 33 string strSql = $"DELETE FROM [{type.Name}] WHERE Id = @Id"; 34 using (SqlConnection conn = new SqlConnection(ConnectionString)) 35 { 36 SqlCommand command = new SqlCommand(strSql, conn); 37 command.Parameters.Add(parameter); 38 conn.Open(); 39 var iRes = command.ExecuteNonQuery(); 40 return iRes > 0 ? true : false; 41 } 42 } 43 44 public List<T> FindAll<T>() where T : BaseModel 45 { 46 Type type = typeof(T); 47 string sqlStr = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM [{type.Name}]"; 48 List<T> list = new List<T>(); 49 using (SqlConnection conn = new SqlConnection(ConnectionString)) 50 { 51 SqlCommand command = new SqlCommand(sqlStr, conn); 52 conn.Open(); 53 var reader = command.ExecuteReader(); 54 while (reader.Read()) 55 { 56 list.Add(this.Trans<T>(type, reader)); 57 } 58 } 59 return list; 60 } 61 62 public T Find<T>(string id) where T : BaseModel 63 { 64 Type type = typeof(T); 65 string sql = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM [{type.Name}] WHERE ID = '{id}' "; 66 object oObject = Activator.CreateInstance(type); 67 using (SqlConnection conn = new SqlConnection(ConnectionString)) 68 { 69 SqlCommand command = new SqlCommand(sql, conn); 70 conn.Open(); 71 var reader = command.ExecuteReader(); 72 if (reader.Read()) 73 return this.Trans<T>(type, reader); 74 else 75 return default(T); 76 } 77 } 78 79 public bool Update<T>(T t) where T : BaseModel 80 { 81 Type type = typeof(T); 82 StringBuilder sb = new StringBuilder(); 83 sb.Append($"UPDATE [{type.Name}] SET "); 84 var propArray = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); 85 var propArrayLen = propArray.Count(); 86 for (int i = 0; i < propArrayLen; i++) 87 { 88 var propertiesName = propArray[i].Name; 89 if (i != propArrayLen - 1) 90 sb.Append($"{propertiesName} = @{propertiesName}, "); 91 else 92 sb.Append($" {propertiesName} = @{propertiesName} "); 93 } 94 #region 使用foreach的寫法 95 //foreach (var properties in propArray) 96 //{ 97 // var propertiesName = properties.Name; 98 // if (i != propArrayLen) 99 // sb.Append($"{propertiesName} = @{propertiesName}, "); 100 // else 101 // sb.Append($" {propertiesName} = @{propertiesName} "); 102 // i++; 103 //} 104 #endregion 105 sb.Append($" Where Id = @Id;"); 106 var parameterList = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => new SqlParameter($"@{p.Name}", p.GetValue(t) ?? DBNull.Value)); 107 using (SqlConnection conn = new SqlConnection(ConnectionString)) 108 { 109 SqlCommand command = new SqlCommand(sb.ToString(), conn); 110 command.Parameters.AddRange(parameterList.ToArray()); 111 conn.Open(); 112 return command.ExecuteNonQuery() > 0; 113 } 114 } 115 116 #region Private Method 117 private T Trans<T>(Type type, SqlDataReader reader) 118 { 119 object oObject = Activator.CreateInstance(type); 120 foreach (var properties in type.GetProperties()) 121 { 122 properties.SetValue(oObject, reader[properties.Name] ?? DBNull.Value); 123 } 124 return (T)oObject; 125 } 126 #endregion 127 }?方法調(diào)用示例代碼:
1 static void Main(string[] args) 2 { 3 BaseDAL baseDAL = new BaseDAL(); 4 { 5 List<User> users = baseDAL.FindAll<User>(); 6 var b = baseDAL.Delete<User>(new User() { 7 Id = "de8be521-f1ec-4483-b124-0be342890507" 8 }); 9 } 10 { 11 var b = baseDAL.Add<User>(new User 12 { 13 Id = Guid.NewGuid().ToString() , 14 Name = "zs", 15 Sex = 0, 16 Status = 1, 17 BizCode = "1234567", 18 CrateId = "123456", 19 TypeId = "123456", 20 TypeName = "admin", 21 CreateTime = DateTime.Now, 22 Account = "wjl", 23 Password = "123456" 24 }); 25 var s = baseDAL.Update<User>(new User 26 { 27 Id = "4955d7e0-808f-4d50-af66-285e2a18966e", 28 Name = "zs", 29 Sex = 0, 30 Status = 1, 31 BizCode = "test value", 32 CrateId = "test value", 33 TypeId = "test value", 34 TypeName = "test value", 35 CreateTime = DateTime.Now, 36 Account = "test value", 37 Password = "test value" 38 }); 39 } 40 Console.ReadLine(); 41 }?至此,常規(guī)的CRUD已基本完成,我們不用再去關注復雜的sql,只需要操作實體類即可。
轉(zhuǎn)載于:https://www.cnblogs.com/netlws/p/11028722.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結(jié)
以上是生活随笔為你收集整理的手写ORM入门篇(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: django基础知识~RBAC实验部分代
- 下一篇: mybatis关联查询