1. 【手撸一个ORM】第一步、约定和实体描述
  2. 【手撸一个ORM】第二步、封装实体描述和实体属性描述
  3. 【手撸一个ORM】第三步、SQL语句构造器和SqlParameter封装
  4. 【手撸一个ORM】第四步、Expression(表达式目录树)扩展
  5. 【手撸一个ORM】第五步、查询条件表达式目录树解析和插入、更新查询目录树解析
  6. 【手撸一个ORM】第六步、对象表达式解析和Select表达式解析
  7. 【手撸一个ORM】第七步、SqlDataReader转实体
  8. 【手撸一个ORM】第八步、实体查询和按需查询
  9. 【手撸一个ORM】第九步、orm默认配置类
  10. 【手撸一个ORM】第十步、数据库查询工具类 MyDb

约定

数据实体对象继承自 IEntity 接口,该接口定义了一个 int 类型的Id属性。

  1. public interface IEntity
  2. {
  3. int Id { get; set; }
  4. }
  5.  
  6. // 数据实体类
  7. public class Student : IEntity
  8. {
  9. public int Id { get; set; }
  10. public string Name { get; set; }
  11. public int ClazzId { get; set; }
  12. public Clazz Clazz { get; set; }
  13.  
  14. // 更新时忽略该属性
  15. [MyColumn(UpdateIgnore = true)]
  16. public DateTime CreateAt { get; set; }
  17. }
  18.  
  19. public class Clazz : IEntity
  20. {
  21. public int Id { get; set; }
  22. public string Name { get; set; }
  23. }

导航属性

如上面定义的Student类,导航属性Clazz默认外键为ClazzId,如需显式指定外键,可使用[MyForeignKey("FKClazzId")]修饰Clazz属性,这样查询时就可以通过Include(s => s.Clazz)查找到相关的Clazz信息,默认仅支持Left Join。

实体描述

MyTableAttribute(string tableName)

用于描述实体类,若实体名称与表名不同,需要使用此描述指定表名

MyKeyAttribute(string keyName)

用于描述实体的主键,若主键列不为Id,需使用词描述指定主键对应的列名

MyColumnAttribute(string ColumnName,bool Ignore,bool InsertIgnore, bool UpdateIgnore)

列描述,可指定对应的列名,Ignore=true 插入和修改时都忽略此字段,InsertIgnore=true 插入时忽略, UpdateIgnore=true 修改时忽略

MyForeignKeyAttribute(string ForeignKey, string MasterKey)

若外键名非 导航属性名+"Id",则需通过ForeignKey指定,MasterKey默认为Id,若不是通过Id进行关联或关联表的主键名不是Id,则需要通过此MasterKey指定

用法

实例化对象:

  1. var db = new MyDb("DataSource=.;Database=Test;USER ID=sa;Password=1234");
  2.  
  3. // 或者在global中定义默认配置,使用时只要 var db = MyDb.New(); 即可。
  4. // MyDb.New()等同于 new MyDb();
  5. MyMiniOrmConfiguration.Init(ConfigurationManager.AppSettings["DefaultConnectionString"]);

查询单个实体:

  1. var student = db.Load<Student>();
  2. var student = db.Load<Student>(s => s.Name == "张三");

查询多个实体:

  1. var student = db.Fetch<Student>();
  2. var student = db.PageList<T>(, , out var recordCount, s => s.Name.Contains("张三"), s=>s.Name);

Fluent 查询

  1. var query = db.Query<Student>()
  2. .Include(s => s.Clazz)
  3. .Where(s => s.CreateAt > DateTime.Today.AddDays(-))
  4. .OrderBy(s => s.Clazz.Id)
  5. .ThenOrderByDesc(s => s.Name);
  6.  
  7. var student = query.FirstOrDefault();
  8. var students = query.ToList();
  9. var students2 = query.ToPageList(, , out var recordCount);

Select 查询

  1. var query = db.Query<Student>()
  2. .Include(s => s.Clazz)
  3. .Where(s => s.CreateAt > DateTime.Today.AddDays(-))
  4. .OrderBy(s => s.Clazz.Id)
  5. .ThenOrderByDesc(s => s.Name);
  6.  
  7. var student = query.Select<StudentDto>(s => new StudentDto { s.Id, s.StudentName, SchoolName = s.School.Name }).ToList();
  8. var student = query.Select<StudentDto>(s => new StudentDto { s.Id, s.StudentName, SchoolName = s.School.Name }).ToPageList(, , out var recordCount);

插入

  1. var student = new Student
  2. {
  3. Name = "张三",
  4. ClazzId = ,
  5. CreateAt = DateTime.Now
  6. };
  7. db.Insert(student); // 会将新产生的Id赋值到student.Id属性
  8. Console.WriteLine($"{student.Id}");
  9.  
  10. // 批量插入
  11. var students = new List<Student>
  12. {
  13. new Student {Name = "张三", ClazzId = , CreateAt = DateTime.Now},
  14. new Student {Name = "李四", ClazzId = , CreateAt = DateTime.Now},
  15. new Student {Name = "王五", ClazzId = , CreateAt = DateTime.Now},
  16. new Student {Name = "赵六", ClazzId = , CreateAt = DateTime.Now}
  17. };
  18.  
  19. db.Insert(students);
  20.  
  21. foreach (var stu in students)
  22. {
  23. Console.WriteLine($"{stu.Id}-{stu.Name}");
  24. }
  25.  
  26. // 如果不存在,则插入
  27. // 如限制用户名不能重复 InsertIfNotExist(user, u => u.Name == user.Name)
  28. int InsertIfNotExists<T>(T entity, Expression<Func<T, bool>> where) where T : class, IEntity, new()

更新

  1. var student = db.Load<Student>();
  2. student.Name = student.Name + "修改过";
  3. var result = db.Update(student);
  4.  
  5. // 批量更新
  6. var students = db.Fetch<Student>(s => s.Id > );
  7. foreach (var student in students)
  8. {
  9. student.Name += student.Name + "批量修改过";
  10. }
  11. var count = db.Update(students);
  12. Console.WriteLine($"修改了 {count} 行");
  13.  
  14. // 如果不存在则更新
  15. // UpdateIfNotExists(user, u=>u.Name == user.Name && u.Id != user.Id)
  16. int UpdateIfNotExits<T>(T entity, Expression<Func<T, bool>> where)

更新

  1. // 通过Id修改指定列
  2. db.Update<Student>(, DbKvs.New().Add("Name", "张三"));
  3.  
  4. var student = db.Load<Student>();
  5. student.Name = student.Name + "测试修改";
  6. student.ClazzId = ;
  7.  
  8. // 更新指定对象的指定属性(指定忽略属性)
  9. // 注意,下面方法传入的是属性名而不是列名
  10.  
  11. var count = db.UpdateInclude<Student>(student, new[] {"Name", "ClazzId"});
  12. var count2 = db.UpdateInclude<Student>(student, s => new { s.Name, s.ClazzId };
  13. var count3 = db.UpdateIgnore<Student>(student, new[] {"CreateAt"});
  14. var count4 = db.UpdateInclude<Student>(student, s => new { s.CreateAt, s.Creator, s.IsDel };
  15.  
  16. // 通过指定条件修改指定列,注意第一个参数传入的是属性名而不是列名
  17. db.Update<Student>(DbKvs.New().Add("ClazzId", ), s => s.ClazzId == );

删除

  1. // 如果实体继承ISoftDelete,此方法将IsDel列赋值为0,可通过传入 isForce=true,强制delete
  2.  
  3. // int Delete<T>(int id, bool isForce = false) where T : class, IEntity, new()
  4. db.Delete<Student>(, true);
  5.  
  6. // int Delete<T>(IEnumerable<int> idList, bool isForce = false) where T : class, IEntity, new()
  7. db.Delete<Student>(new[] {,,}, true);

【手撸一个ORM】MyOrm的使用说明的更多相关文章

  1. 【手撸一个ORM】第六步、对象表达式解析和Select表达式解析

    说明 一个Orm自然不仅仅包含条件表达式,还会有如下的场景: OrderBy(s => s.StudentName) Select<StudentDto>(s => new S ...

  2. 【手撸一个ORM】第七步、SqlDataReader转实体

    说明 使用Expression(表达式目录树)转Entity的文章在园子里有很多,思路也大致也一样,我在前面有篇文章对解决思路有些说明,有兴趣的小伙伴可以看下 (传送门),刚接触表达式目录树时写的,不 ...

  3. 【手撸一个ORM】第十步、数据操作工具类 MyDb

    说明 其实就是数据库操作的一些封装,很久不用SqlCommand操作数据库了,看了点园子里的文章就直接上手写了,功能上没问题,但写法上是否完美高效无法保证,建议有需要的朋友自己重写,当然如果能把最佳实 ...

  4. 【手撸一个ORM】第一步、实体约定和描述

    一.约定 数据实体必须实现 IEntity 接口,该接口定义了一个int类型的Id属性,既每个实体必须有一个名称为Id的自增主键. 若数据表的主键列名称不是Id,可以通过 [MyKey("主 ...

  5. 【手撸一个ORM】第三步、SQL语句构造器和SqlParameter封装

    既然是数据库工具,自然少不了增删改查的sql语句,在这里将这些常用SQL拼接操作集成到 [SqlServerBuilder.cs] 当中,方便后面调用. 近几年在项目中一直使用Dapper操作数据库, ...

  6. 【手撸一个ORM】第四步、Expression(表达式目录树)扩展

    到这里,Orm的基架已经搭起来了,接下来就是激动人心的部分,表达式目录树转Sql语句,SqlDataReader转数据实体等等,但是在这之前,我们需要扩展下表达式目录树的方法,以方便后面的相关操作. ...

  7. 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句

    说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...

  8. 【手撸一个ORM】第八步、查询工具类

    一.实体查询 using MyOrm.Commons; using MyOrm.DbParameters; using MyOrm.Expressions; using MyOrm.Mappers; ...

  9. 【手撸一个ORM】第二步、封装实体描述和实体属性描述

    一.实体属性描述 [MyProperty.cs] Name,属性名称 PropertyInfo,反射获取的属性信息,后面很多地方需要通过该属性获取对应的实体类型,或调用SetValue进行赋值 Fie ...

随机推荐

  1. NOIp2018集训test-10-16 (bike day2)

    “毕姥爷:今天的题好简单啊,你们怎么考得这么烂啊,如果是noip你们就凉透了啊“ 今天的题难度应该是3.2.1递减的,但是我不知道哪根筋没搭对,平时我最多1h多就弃题了,今天硬生生写了2h20min的 ...

  2. Hibernate Validator--创建自己的约束规则

    尽管Bean Validation API定义了一大堆标准的约束条件, 但是肯定还是有这些约束不能满足我们需求的时候, 在这种情况下, 你可以根据你的特定的校验需求来创建自己的约束条件. 3.1. 创 ...

  3. spring扩展点之四:Spring Aware容器感知技术,BeanNameAware和BeanFactoryAware接口,springboot中的EnvironmentAware

    aware:英 [əˈweə(r)] 美 [əˈwer] adj.意识到的;知道的;觉察到的 XXXAware在spring里表示对XXX感知,实现XXXAware接口,并通过实现对应的set-XXX ...

  4. WPF实现右键菜单

    ContextMenu类就是用来做右键菜单的对象,对于任何的控件都可以进行对ContextMenu属性的操作进行设置右键菜单的功能. 下面代码就是对一个按钮添加一个WPF右键菜单的功能: < B ...

  5. Asp.net 实现只能允许一个账号同时只能在一个地方登录

    先上帮助类: /// <summary> /// 单点登录帮助类 /// </summary> public class SSOHelper { /// <summary ...

  6. Matlab数据类型的转换

    Matlab中有15种基本数据类型,主要是整型.浮点.逻辑.字符.日期和时间.结构数组.单元格数组以及函数句柄等. 1.整型:(int8:uint8:int16:uint16:int32:uint32 ...

  7. Angular06 组件、模块、父子组件之间的数据传递

    1 创建组件 进入到angular项目的根目录,执行如下命令 ng g component test-component 注意:执行完上述命令后在angular项目的src/app文件夹下就会多出一个 ...

  8. Mail.Ru Cup 2018 Round 2C(__gcd)

    #include<bits/stdc++.h>using namespace std;long long mx(long long l1,long long r1,long long l2 ...

  9. java排序算法(持续更新)

    package exception; import java.util.Arrays; public class Sort { public static void main(String[] arg ...

  10. uva 1153 顾客是上帝(贪心)

    uva 1153 顾客是上帝(贪心) 有n个工作,已知每个工作需要的时间q[i]和截止时间d[i](必须在此前完成),最多能完成多少个工作?工作只能串行完成,第一项任务开始的时间不早于时刻0. 这道题 ...