博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手写ORM入门篇(一)
阅读量:6994 次
发布时间:2019-06-27

本文共 9109 字,大约阅读时间需要 30 分钟。

对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。

面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。

对象关系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化数据的方法。ORM方法论基于三个核心原则: 简单:以最基本的形式建模数据。 传达性:数据库结构被任何人都能理解的语言文档化。 精确性:基于数据模型创建正确标准化的结构。 典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次上与数据结构进行通讯。建模者也必须能以简单的单元分析信息,对样本数据进行处理。ORM专门被设计为改进这种联系。

简单的说:ORM相当于中继数据。具体到产品上,例如ADO.NET Entity Framework。DLINQ中实体类的属性[Table]就算是一种中继数据。

BaseModel示例代码:

1     public class BaseModel2     {3         /// 4         /// 所有实体的父类,非自增主键GUID5         /// 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         ///  4         /// 根据主键返回一个实体 5         ///  6         /// 
7 /// 8 ///
9 T Find
(string id) where T : BaseModel;10 11 ///
12 /// 返回一个List
实体集合13 ///
14 ///
15 ///
16 List
FindAll
() where T : BaseModel;17 18 ///
19 /// 添加一条记录20 /// 21 ///
22 ///
23 ///
24 bool Add
(T t) where T : BaseModel;25 26 ///
27 /// 更新一个实体28 /// 29 ///
30 ///
31 ///
32 bool Update
(T t) where T : BaseModel;33 34 ///
35 /// 删除一条记录36 /// 37 ///
38 ///
39 ///
40 bool Delete
(T t) where T : BaseModel;41 }

BaseDAL示例代码

1     ///   2     /// 泛型方法添加BaseModel约束,所有实体类必须有一个非自增的主键Id,Id的值为随机的GUID,  3     ///   4     public class BaseDAL : IBaseDAL  5     {  6         ///   7         /// 数据库连接字符串  8         ///   9         private static string ConnectionString = ConfigurationManager.ConnectionStrings["OpenAuthDB"].ConnectionString; 10  11         public bool Add
(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) 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
FindAll
() 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
list = new List
(); 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
(type, reader)); 57 } 58 } 59 return list; 60 } 61 62 public T Find
(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
(type, reader); 74 else 75 return default(T); 76 } 77 } 78 79 public bool Update
(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 // else101 // sb.Append($" {propertiesName} = @{propertiesName} ");102 // i++;103 //}104 #endregion105 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 Method117 private T Trans
(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 #endregion127 }

 方法调用示例代码:

1         static void Main(string[] args) 2         { 3             BaseDAL baseDAL = new BaseDAL(); 4             { 5                 List
users = baseDAL.FindAll
(); 6 var b = baseDAL.Delete
(new User() { 7 Id = "de8be521-f1ec-4483-b124-0be342890507" 8 }); 9 }10 {11 var b = baseDAL.Add
(new User12 {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
(new User26 {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 }

 至此,常规的CRUD已基本完成,我们不用再去关注复杂的sql,只需要操作实体类即可。

转载于:https://www.cnblogs.com/netlws/p/11028722.html

你可能感兴趣的文章
.NET简谈事务、分布式事务处理
查看>>
Windows操作系统的发展历史
查看>>
拆分又遇变数,传赛门铁克或将出售VERITAS,这又是挖的什么坑?
查看>>
UGC“废水”还是“良药”?56、人人"抱团"上路
查看>>
SCCM2012系列之十一,SCCM2012软件更新部署配置
查看>>
也谈大公司病4——大公司中的反模式
查看>>
基于IP-PBX的VoIP系统解决方案
查看>>
《Python从小白到大牛》第1章 开篇综述
查看>>
Word 2003中为什么修改一个段落的文章结果整篇文档的格式都变?
查看>>
安装 SQL Server Express 版本
查看>>
部署Lync Server 2013持久聊天即群聊功能
查看>>
VMware View 5.0从菜鸟到高手系列 7 -分配虚拟桌面篇
查看>>
Hyper-V 3虚拟机快照之一 快照应用介绍
查看>>
ASP.NET中页面传值
查看>>
Flex4中动态生成RadioButton,绑定数据源
查看>>
开源CMS大PK:WordPress vs Drupal vs Joomla ,谁更强大更好用
查看>>
HDU-1004 Let the Balloon Rise STL map
查看>>
单片机低功耗设计杂谈
查看>>
Ubuntu上怎么安装Eclipse Android 开发环境
查看>>
转载:解答Google的一道面试题
查看>>