手写ORM入门篇(一)
对象关系映射(英语:(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 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 /// 根据主键返回一个实体 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 /// 数据库连接字符串 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 }
方法调用示例代码:
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 }
至此,常规的CRUD已基本完成,我们不用再去关注复杂的sql,只需要操作实体类即可。
转载于:https://www.cnblogs.com/netlws/p/11028722.html
手写ORM入门篇(一)相关推荐
- 手写ORM框架----(数据库单表CRUD万能框架)
目录 一.准备 1.1 ORM介绍 1.2 准备工作 二.手写ORM的CRUD 2.1 数据库准备 2.2 所需注解 2.3 实体类student 2.4 CRUD 2.4.1 添加功能 2.4.2 ...
- 【Java ORM】手写ORM框架:源代码、jar、生成JavaDoc文档
SORMSourceCode 把这个手写框架取名为SORM. (1)源代码(Eclipse项目文件):GitHub地址 (2)jar包.源代码.JavaDoc文档.使用说明:Github地址 一个简单 ...
- 前端为什么有的接口明明是成功回调却执行了.catch失败回调_前端进阶高薪必看-手写源码篇(高频技术点)...
前言 此系列作为笔者之前发过的前端高频面试整理的补充 会比较偏向中高前端面试问题 当然大家都是从新手一路走过来的 感兴趣的朋友们都可以看哈 初衷 我相信不少同学面试的时候最怕的一个环节就是手写代码 大 ...
- all方法 手写promise_前端进阶高薪必看手写源码篇
前言 此系列作为笔者之前发过的前端高频面试整理的补充 会比较偏向中高前端面试问题 当然大家都是从新手一路走过来的 感兴趣的朋友们都可以看哈 初衷 我相信不少同学面试的时候最怕的一个环节就是手写代码 大 ...
- 手写字符识别入门学习记录(1)
最近由于项目需要,开始学习OCR,查看了一些资料,测试了一些软件的OCR效果,包括ABBYY.汉王.尚书7号等,还是手机端的扫描全能王,这些软件对印刷书写体的扫描图像的OCR识别效果还可以,但是针对手 ...
- 手写Promise-最终篇
前言 这里呢是我写的全部promise源码,包含以下功能1.promise核心函数 2.promise核心函数resolve() 3.promise核心函数reject()4.then方法链式调用 5 ...
- Paddle:手写字符总结篇
数据集的预处理 ## 数据的生成器 # 加载相关库 import os import random import paddle import paddle.fluid as fluid from pa ...
- Java手写HashSet
一:引言 HashSet类继承于 Set接口 其方法均可被直接调用,不用手写,本篇敲的码是为了熟悉底层原理,HashMap的特点:无序,无重复.其底层用的也是map<key,value>容 ...
- Java手写Hashmap(HashMap的基本用法)
一:引言 HashMap是Map的实现类,其方法都可以继承Map,不用手写,本篇只是为了了解底层代码和复习java基础敲得码 二:上码 package cn.wyj.two;public class ...
最新文章
- pandas从dataframe中删除一个或多个数据列
- 开发日记-20190426 关键词 无限分级界面
- ASP.NET MVC 上传文件
- ArcGIS JS API中切换页面后组件报Tried to register widget with id== but that id is already registered
- DL之DNN:利用DNN【784→50→100→10】算法对MNIST手写数字图片识别数据集进行预测、模型优化
- 警告!你的Python代码命名太烂了,命令你熟读本篇迷你命名指南!
- excel二极管伏安特性曲线_【刘敏蔷老师】半导体二极管的原理及应用
- 神经网络训练3次就准确率不变_1组高效徒手训练,6个动作每周3-5次,帮你在家高效率燃脂增肌!...
- 剑指offer 11.旋转数组的最小数字
- java能看懂代码不会写_为什么很多学习Java的人能看懂代码,但就是不会写!
- java IoT物联网server 读取javascript协议配置文件
- Java编程:排序算法——基数排序
- CentOS中MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解
- 如何看懂常用原理图符号、如何阅读原理图
- 编写程序实现输入一个不超过100的十进制正整数,输出与其相等的二进制形式
- Python项目实战:各种小说姓名生成器
- 全国大学生软件测试大赛Web应用测试(五)Jmeter性能测试环境配置
- Navicat连接mysql时出现 Access denied for user ‘root‘@‘xxx.xxx.xxx.xxx‘ (using password: YES) 的原因及解决办法。
- 【DOTS学习笔记】DOTS简介
- kinect V2 驱动安装说明
热门文章
- boost::log相关用法的测试程序
- boost::edge_list用法的测试程序
- GDCM:DICOM PS 3.10文件格式的测试程序
- Boost:宏BOOST_TEST_EQ的测试
- ITK:使用Deformation Field扭曲图像
- ITK:Levenberg-Marquardt优化
- DCMTK:测试字符串OFString实用程序
- DCMTK:父元素处理的测试程序
- OpenGL pointsprites点精灵的实例
- QT的QNetworkDiskCache类的使用