一、约定

数据实体必须实现 IEntity 接口,该接口定义了一个int类型的Id属性,既每个实体必须有一个名称为Id的自增主键。

若数据表的主键列名称不是Id,可以通过 [MyKey("主键列名")] 对该属性进行描述

  1. namespace MyOrm.Commons
  2. {
  3. public interface IEntity
  4. {
  5. int Id { get; set; }
  6. }
  7. }

二、实体描述

MyTableAttribute,用于约定实体和数据表的关联关系,若实体名称和数据表名一直,可省略此描述

MyKeyAttribute,用于约定实体的主键,若数据表主键名称不是Id,可通过此描述约定Id属性映射的数据表的主键名

MyColumnAttribute,InsertIgnore=true 插入时忽略此属性;UpdateIgnore=true 更新时忽略此属性;Ignore=true 插入和更新时忽略该属性;ColumnName 若属性名和列名不一致,使用此属性约定映射的数据表列名

MyForeignKeyAttribute,ForeignKey 用于约定导航属性和外键列,若外键名不为 “导航属性名 + Id”,则需要通过此描述进行约定。

  1. using System;
  2.  
  3. namespace MyOrm.Attributes
  4. {
  5. [AttributeUsage(AttributeTargets.Class)]
  6. public class MyTableAttribute : Attribute
  7. {
  8. public string TableName { get; }
  9.  
  10. public MyTableAttribute(string tableName)
  11. {
  12. TableName = tableName;
  13. }
  14. }
  15.  
  16. [AttributeUsage(AttributeTargets.Property)]
  17. public class MyKeyAttribute : Attribute
  18. {
  19. public bool IsIncrement { get; set; } = true;
  20.  
  21. public string FieldName { get; set; }
  22. }
  23.  
  24. [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
  25. public class MyColumnAttribute : Attribute
  26. {
  27. public string ColumnName { get; set; }
  28.  
  29. public bool Ignore { get; set; }
  30.  
  31. public bool InsertIgnore { get; set; }
  32.  
  33. public bool UpdateIgnore { get; set; }
  34. }
  35.  
  36. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
  37. public class MyForeignKeyAttribute : Attribute
  38. {
  39. public string ForeignKey { get; set; }
  40.  
  41. public string MasterKey { get; set; } = "Id";
  42.  
  43. public MyForeignKeyAttribute(string foreignKey)
  44. {
  45. ForeignKey = foreignKey;
  46. }
  47. }
  48. }

三、示例:

  1. using MyOrm.Attributes;
  2. using MyOrm.Commons;
  3. using System;
  4.  
  5. namespace ConsoleApp1
  6. {
  7. // 实体对应的数据表名为 Base_Student
  8. [MyTable("Base_Student")]
  9. public class Student : IEntity
  10. {
  11. // 数据表的主键名称为StudentId
  12. [MyKey(FieldName = "StudentId")]
  13. public int Id { get; set; }
  14.  
  15. public string StudentName { get; set; }
  16.  
  17. public string Mobile { get; set; }
  18.  
  19. public string Card { get; set; }
  20.  
  21. public string State { get; set; }
  22.  
  23. public DateTime? Birthday { get; set; }
  24.  
  25. // 更新时忽略学校Id
  26. [MyColumn(UpdateIgnore = true)]
  27. public int FKSchoolId { get; set; }
  28.  
  29. // 是否删除字段只能通过 Delete 方法修改,Update时需忽略该属性
  30. [MyColumn(UpdateIgnore = true)]
  31. public bool IsDel { get; set; }
  32.  
  33. // 创建时间和创建人只在创建时指定,其他时候不能修改
  34. [MyColumn(UpdateIgnore = true)]
  35. public DateTime CreateAt { get; set; }
  36.  
  37. [MyColumn(UpdateIgnore = true)]
  38. public string CreateBy { get; set; }
  39.  
  40. public DateTime UpdateAt { get; set; }
  41.  
  42. public string UpdateBy { get; set; }
  43.  
  44. // 导航属性的外键为 FKSchoolId,若不指定,默认为SchoolId
  45. [MyForeignKey("FKSchoolId")]
  46. public School School { get; set; }
  47. }
  48. }

【手撸一个ORM】第一步、实体约定和描述的更多相关文章

  1. 【手撸一个ORM】MyOrm的使用说明

    [手撸一个ORM]第一步.约定和实体描述 [手撸一个ORM]第二步.封装实体描述和实体属性描述 [手撸一个ORM]第三步.SQL语句构造器和SqlParameter封装 [手撸一个ORM]第四步.Ex ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 分享知识-快乐自己:SpringBoot结合使用拦截器(判断是否用户是否已登陆)

    所有的开发之中拦截器一定是一个必须要使用的功能,利用拦截器可以更加有效的实现数据的验证处理,而且最为幸运的是在SpringBoot之中所使用的拦截器与Spring中的拦截器完全一样. 基础拦截器操作: ...

  2. app测试点-1

    一.安全测试 1.软件权限 1)扣费风险:包括短信.拨打电话.连接网络等. 2)隐私泄露风险:包括访问手机信息.访问联系人信息等. 3)对App的输入有效性校验.认证.授权.数据加密等方面进行检测 4 ...

  3. mybatis进行分页,使用limit

    这里记录两个思路: 首先是写一个不能执行的代码. <select id="query" parameterType="map" resultType=&q ...

  4. 线程绑定CPU核-sched_setaffinity

    CPU亲合力就是指在Linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行. 一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行.在一个多处理器系统中,设置CPU亲合力的掩码 ...

  5. vue文件名规范

    之前有看过一些命名规范,也看到说vue文件命名要么全是小写要么就是用小写 + '-':其实看到的时候有点不以意,因为本地能跑起项目:发布能正常访问也就OK了. 但是今天在做自动化部署的时候碰到一个问题 ...

  6. Vue cli项目开启Gzip

    目录 安装 compression-webpack-plugin 更改配置文件 服务器开启gzip功能 安装 compression-webpack-plugin 建议安装v1.1.11版本,最新版本 ...

  7. poj3281Dining——网络流匹配

    题目:http://poj.org/problem?id=3281 网络流做图中的匹配,注意为了限制每头牛只匹配一种食物和一种饮料,要把牛拆成两个点,之间连边权为1的边. 代码如下: #include ...

  8. C# 获取Console的输入和输出 数据 (异步)

    using System ; using System .Diagnostics; using System .IO;   class Program {     static void Main() ...

  9. httpd服务相关实验

    实验环境: CentOS6.8 1.连接测试: 在/etc/httpd/conf/httpd.conf telnet 172.16.252.242 80 GET /index.html HTTP/1. ...

  10. JS极品日历

    <!DOCTYPE><html><head><meta http-equiv="Content-Type" content="t ...