快速传送

手撸ORM浅谈ORM框架之基础篇

手撸ORM浅谈ORM框架之Add篇

手撸ORM浅谈ORM框架之Update篇

手撸ORM浅谈ORM框架之Delete篇

手撸ORM浅谈ORM框架之Query篇

后续待定。。。。。。

合抱之木,生于毫末

反射

在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

手撸ORM浅谈ORM框架系列使用反射机制来实现的动态获取所需要的信息,反射机制有优点也有缺点,使用了反射我们可以不用每次更新实体模型数据访问层转换Sql等很多需要修改的地方,享受快捷便利的同时肯定会带来相应的缺点,反射的性能在执行同样的操作时会略低于直接使用强类型语言的原生特性,毕竟它至少多了动态获取信息步骤;我们不能因此否认反射,反射确实在很多场景可以为我们做很多不必要的重复性工作,可以节约出时间做更棘手的问题。

对于我们需要使用什么决定因素需要看使用前后的变化,利大于弊且符合业务需要就放心使用,完美不存在,更美从未止步。。。

泛型

泛型(摘录百度百科:泛型)

由于.NET Framework 泛型的类型参数之实际类型在运行时均不会被消除,运行速度会因为类型转换的次数减少而加快。Java 泛型的参数只可以代表类,不能代表个别对象。由于 Java 泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。

九层之台,起于累土

主要通过反射获取实体信息,目前项目中的实体唯一主键统一使用的bigint自动递增。

BaseRepository-》GetCurrentTableName获取表名称;

 1 /// <summary>
2 /// get current-table-name
3 /// </summary>
4 /// <returns>return table-name</returns>
5 private string GetCurrentTableName()
6 {
7 string currentTableName = string.Empty;
8 var t = typeof(T);
9 if (t != null && !t.Name.IsNullOrEmpty())
10 {
11 currentTableName = t.Name;
12 }
13 if (currentTableName.IsNullOrEmpty())
14 {
15 throw new ArgumentNullException("get table-name is null");
16 }
17 return currentTableName;
18 }

BaseRepository-》GetExcludeKeyAllFields获取主键以外的public字段;

 1 /// <summary>
2 /// get exclude key all fields
3 /// </summary>
4 /// <returns>return exclude key all fields</returns>
5 private List<PropertyInfo> GetExcludeKeyAllFields()
6 {
7 PropertyInfo[] properties = typeof(T).GetProperties();
8 // filter abstract virtual property
9 properties = properties.Where(p => p.PropertyType.IsAbstract == false && !p.GetMethod.IsVirtual == true).ToArray();
10 if (properties == null || properties.Length <= 0)
11 {
12 throw new ArgumentNullException("public value fields is null");
13 }
14 List<PropertyInfo> list = new List<PropertyInfo>();
15 foreach (var item in properties)
16 {
17 if (item.CustomAttributes.Any(c => c.AttributeType.Name == nameof(KeyAttribute)))
18 {
19 continue;
20 }
21 list.Add(item);
22 }
23 if (list == null || list.Count <= 0)
24 {
25 throw new ArgumentNullException("public value fields is null");
26 }
27 return list;
28 }

BaseRepository-》GetValue获取字段对应的值,String和Char前面分别加了N前缀(Sql Server反射弧),MySql中文字符可加或不加中文字段不会出现乱码,若出现乱码可以根据实际情况设置MySql数据库字符集的格式;

 1 /// <summary>
2 /// get value
3 /// </summary>
4 /// <param name="property"></param>
5 /// <param name="entity"></param>
6 /// <returns></returns>
7 private string GetValue(PropertyInfo property , T entity)
8 {
9 var val = property.GetValue(entity);
10 if (val == null)
11 {
12 return "NULL";
13 }
14 else
15 {
16 string prefixN = string.Empty;
17 if (property.PropertyType.Name == nameof(String) || property.PropertyType.Name == nameof(Char))
18 {
19 prefixN = "N";
20 }
21 if (property.PropertyType.Name == nameof(Boolean))
22 {
23 return string.Format("{0}", GetBoolValue(val));
24 }
25 return string.Format("{0}'{1}'", prefixN, val);
26 }
27 }

BaseRepository-》GetBoolValue值属性转换,Sql Server中数据类型bit:'true' or 'false' 等同于'1' or '0';MySql 8.x数据类型bit: 需要把bool 'true' or 'false' 转换成'1' or '0' 。目前项目中使用到的数据类型bigint、varchar、int、char、datetime、bit,bit->需要转换;

 1 /// <summary>
2 /// get bool value
3 /// mysql true or false convert 1 or 0
4 /// </summary>
5 /// <param name="obj"></param>
6 /// <returns></returns>
7 private int GetBoolValue(object obj)
8 {
9 //return obj.ToString().ToLower() == "false" ? 0 : 1;
10 if (obj.ToString().ToLower() == "false")
11 {
12 return 0;
13 }
14 return 1;
15 }

BaseRepository-》GetInsertSql一路走来Sql出现了(提高性能可以优化,缓存当前项目所有表的增删查改Sql语句)

 1 /// <summary>
2 /// get insert sql
3 /// </summary>
4 /// <param name="entity">entity</param>
5 /// <returns>return insert sql</returns>
6 private string GetInsertSql(T entity)
7 {
8 string tableName = GetCurrentTableName();
9 StringBuilder sbField = new StringBuilder();
10 StringBuilder sbValue = new StringBuilder();
11 PropertyInfo[] properties = GetAllFields(true);
12 foreach (var item in properties)
13 {
14 sbField.AppendFormat("{0},", item.Name);
15 sbValue.AppendFormat("{0},", GetValue(item, entity));
16 }
17 sbField.Remove(sbField.Length - 1, 1);
18 sbValue.Remove(sbValue.Length - 1, 1);
19 //todo ;SELECT @@identity return identity
20 return string.Format("INSERT INTO {0} ({1}) VALUES ({2})", tableName, sbField, sbValue);
21 }

BaseRepository-》Add千呼万唤始出来,终于到写入数据库了(Add成功后没有返回实体因为NET Core的DbContext取消了SqlQuery,基类BaseRepository实现Add后返回当前的实体主键,基本原生 SQL 查询可使用 FromSqlRaw 扩展方法基于原始 SQL 查询开始 LINQ 查询。 FromSqlRaw 只能在直接位于 DbSet<> 上的查询根上使用;NET Framework DBContext中有此方法SqlQuery,可以使用Query在Insert语句后面;SELECT @@identity返回int、bigint类型自动递增主键并赋值给当前实体,如果是指定主键直接返回当前实体,也期待园友提出更好的解决方案)

 1 /// <summary>
2 /// add entity
3 /// </summary>
4 /// <param name="entity">entity</param>
5 /// <returns>return true or false</returns>
6 public bool Add(T entity)
7 {
8 string sql = GetInsertSql(entity);
9 context.Database.ExecuteSqlRaw(sql);
10 return true;
11 }

实操Repository方法泛型约束

 1 /// <summary>
2 /// LearnStudentRepository
3 /// </summary>
4 public partial class LearnStudentRepository: ILearnStudentRepository
5 {
6 public bool Add(Learn_Student learnStudent)
7 {
8 using (MySqlDbContext mySqlDbContext=new MySqlDbContext())
9 {
10 BaseRepository<Learn_Student> baseRepository = new BaseRepository<Learn_Student>(mySqlDbContext);
11 return baseRepository.Add(learnStudent);
12 }
13 }
14 }

登高望远,更上层楼

learn-orm-net缺少以下情况的处理:

  • 1. Sql语句没有缓存,缓存提高一些性能;
  • 2.不支持指定主键的实体,既是已经提前把主键生成好了;
  • 3.项目使用的实体是自动递增主键并且没有返回主键的值,不能满足主子表有外键关系业务场景,既是子表存主表的主键(自动递增类型主键);
  • 4.复合主键(主键都是指定主键,提前按照一定规则生成的键值);
  • 5.复合主键里面包含自增主键,既是有指定类型主键也有自动递增类型主键;
  • 6.实体包含导航属性级联写入数据库(类似于3)
  • (如果业务需要特殊的方式,ORM框架没有我们可以写基类方法或者扩展方法来适应项目需要,待补充...)
  • 注:learn-orm-net目前只是作为学习ORM框架原理的Demo,项目会做出一定的优化处理,但不能直接拿来在项目中使用,毕竟现在NET Framework、NET Core已经有很多优秀的ORM框架,NET下一次发布就是只有一个版本了,我们没有必要重复造轮子,造轮子是因为没有现成的优秀的轮子可用。

如果只是停留在会使用当前项目所使用的ORM框架基本增删查改,对于根据业务更好的使用ORM框架是有点困难的;所以,深入理解ORM原理,为未来的某个时刻我们遇到了问题,更好的根据ORM框架有的功能做出比较符合业务需要的程序;或者,扩展当前ORM框架没有的功能来适应我们项目的业务需求。

代码下载地址: SourceCode  作者水平有限欢迎园友纠正错误及不恰当之处,予以及时修正以免误导他人!

手撸ORM浅谈ORM框架之Add篇的更多相关文章

  1. 手撸ORM浅谈ORM框架之基础篇

    好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...

  2. 手撸ORM浅谈ORM框架之Update篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  3. 手撸ORM浅谈ORM框架之Delete篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  4. 手撸ORM浅谈ORM框架之Query篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  5. 手撸基于swoole 的分布式框架 实现分布式调用(20)讲

    最近看的一个swoole的课程,前段时间被邀请的参与的这个课程 比较有特点跟一定的深度,swoole的实战教程一直也不多,结合swoole构建一个新型框架,最后讲解如何实现分布式RPC的调用. 内容听 ...

  6. 【SSH学习笔记】浅谈SSH框架

    说在前面 本学期我们有一门课叫做Java EE,由陈老师所授,主要讲的就是Java EE 中的SSH框架. 由于陈老师授课风格以及自己的原因导致学了整整一学期不知道在讲什么,所以才有了自己重新学习总结 ...

  7. 浅谈chainer框架

    一 chainer基础 Chainer是一个专门为高效研究和开发深度学习算法而设计的开源框架. 这篇博文会通过一些例子简要地介绍一下Chainer,同时把它与其他一些框架做比较,比如Caffe.The ...

  8. 浅谈ORM操作

    2. ORM(对象关系映射) 1. 映射的关系 DB ORM 数据表 <--> 类 数据行 <--> 对象 字段 <--> 属性 2. Django项目使用MySQ ...

  9. 【带你手撸Spring】没有哪个框架开发,能离开 Spring 的 FactoryBean!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老司机,你的砖怎么搬的那么快? 是有劲?是技巧?是后门?总之,那个老司机的代码总是可 ...

随机推荐

  1. 关于java基础语法的学习笔记

    *java语言特点 1,简单易用 2,跨平台 拥有JVM虚拟机(运行程序) 3,面向对象 4,支持多线程*java核心机制 1,java虚拟机 JVM 2,垃圾回收机制*JDK和JRE JDK JRE ...

  2. hystrix动态修改参数

    Hystrix 从入门到深入——运行时修改动态配置 /** * * @author zhangshuo * */ @Component public class DynamicConfigSource ...

  3. ribbon源码之客户端

    客户端模块的核心功能是提供统一的用户请求操作接口. 接口定义 客户端模块的核心是IClient接口,定义了客户端网络请求的方法. public interface IClient<S exten ...

  4. 利用adb查看手机设备ip和连接手机的两种方式

    电脑安装adb(查看菜鸟adb教程) [cmd]->输入adb devices (设置了path,否则需要 ./路径/adb devices)如图: 查看ip两种方法(可能有更多,目前我还没看到 ...

  5. APS定时任务框架

    一.安装与简介 1.安装 pip install apscheduler 官方文档:https://apscheduler.readthedocs.io/en/latest/# 2.简介 APSche ...

  6. Git【常见知识点速查】

    文章更新时间:2020/06/17 一.基础知识点解析 Git工作流程 以上包括一些简单而常用的命令,但是先不关心这些,先来了解下面这4个专有名词. Workspace:工作区 Index / Sta ...

  7. Java并发编程之ReentrantLock源码分析

    ReentrantLock介绍 从JDK1.5之前,我们都是使用synchronized关键字来对代码块加锁,在JDK1.5引入了ReentrantLock锁.synchronized关键字性能比Re ...

  8. 64位Win7下H3C的iMC无法查看“网络拓扑”的解决方法、心路历程

    64位Win7下H3C的iMC无法查看"网络拓扑"的解决方法.心路历程

  9. 005 01 Android 零基础入门 01 Java基础语法 01 Java初识 05 Eclipse简介

    005 01 Android 零基础入门 01 Java基础语法 01 Java初识 05 Eclipse简介 Eclipse是一款集成开发工具--IDE. 集成开发环境(IDE,Integrated ...

  10. 01 AS 首次编译执行项目过程中遇到的几个常见问题

    问题01 as打开时出现The environment variable JAVA_HOME (with The value of C:\Java\jdk1.8.0_101\bin) does not ...