【手撸一个ORM】第一步、实体约定和描述
一、约定
数据实体必须实现 IEntity 接口,该接口定义了一个int类型的Id属性,既每个实体必须有一个名称为Id的自增主键。
若数据表的主键列名称不是Id,可以通过 [MyKey("主键列名")] 对该属性进行描述
namespace MyOrm.Commons
{
public interface IEntity
{
int Id { get; set; }
}
}
二、实体描述
MyTableAttribute,用于约定实体和数据表的关联关系,若实体名称和数据表名一直,可省略此描述
MyKeyAttribute,用于约定实体的主键,若数据表主键名称不是Id,可通过此描述约定Id属性映射的数据表的主键名
MyColumnAttribute,InsertIgnore=true 插入时忽略此属性;UpdateIgnore=true 更新时忽略此属性;Ignore=true 插入和更新时忽略该属性;ColumnName 若属性名和列名不一致,使用此属性约定映射的数据表列名
MyForeignKeyAttribute,ForeignKey 用于约定导航属性和外键列,若外键名不为 “导航属性名 + Id”,则需要通过此描述进行约定。
using System; namespace MyOrm.Attributes
{
[AttributeUsage(AttributeTargets.Class)]
public class MyTableAttribute : Attribute
{
public string TableName { get; } public MyTableAttribute(string tableName)
{
TableName = tableName;
}
} [AttributeUsage(AttributeTargets.Property)]
public class MyKeyAttribute : Attribute
{
public bool IsIncrement { get; set; } = true; public string FieldName { get; set; }
} [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class MyColumnAttribute : Attribute
{
public string ColumnName { get; set; } public bool Ignore { get; set; } public bool InsertIgnore { get; set; } public bool UpdateIgnore { get; set; }
} [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class MyForeignKeyAttribute : Attribute
{
public string ForeignKey { get; set; } public string MasterKey { get; set; } = "Id"; public MyForeignKeyAttribute(string foreignKey)
{
ForeignKey = foreignKey;
}
}
}
三、示例:
using MyOrm.Attributes;
using MyOrm.Commons;
using System; namespace ConsoleApp1
{
// 实体对应的数据表名为 Base_Student
[MyTable("Base_Student")]
public class Student : IEntity
{
// 数据表的主键名称为StudentId
[MyKey(FieldName = "StudentId")]
public int Id { get; set; } public string StudentName { get; set; } public string Mobile { get; set; } public string Card { get; set; } public string State { get; set; } public DateTime? Birthday { get; set; } // 更新时忽略学校Id
[MyColumn(UpdateIgnore = true)]
public int FKSchoolId { get; set; } // 是否删除字段只能通过 Delete 方法修改,Update时需忽略该属性
[MyColumn(UpdateIgnore = true)]
public bool IsDel { get; set; } // 创建时间和创建人只在创建时指定,其他时候不能修改
[MyColumn(UpdateIgnore = true)]
public DateTime CreateAt { get; set; } [MyColumn(UpdateIgnore = true)]
public string CreateBy { get; set; } public DateTime UpdateAt { get; set; } public string UpdateBy { get; set; } // 导航属性的外键为 FKSchoolId,若不指定,默认为SchoolId
[MyForeignKey("FKSchoolId")]
public School School { get; set; }
}
}
【手撸一个ORM】第一步、实体约定和描述的更多相关文章
- 【手撸一个ORM】MyOrm的使用说明
[手撸一个ORM]第一步.约定和实体描述 [手撸一个ORM]第二步.封装实体描述和实体属性描述 [手撸一个ORM]第三步.SQL语句构造器和SqlParameter封装 [手撸一个ORM]第四步.Ex ...
- 【手撸一个ORM】第十步、数据操作工具类 MyDb
说明 其实就是数据库操作的一些封装,很久不用SqlCommand操作数据库了,看了点园子里的文章就直接上手写了,功能上没问题,但写法上是否完美高效无法保证,建议有需要的朋友自己重写,当然如果能把最佳实 ...
- 【手撸一个ORM】第六步、对象表达式解析和Select表达式解析
说明 一个Orm自然不仅仅包含条件表达式,还会有如下的场景: OrderBy(s => s.StudentName) Select<StudentDto>(s => new S ...
- 【手撸一个ORM】第七步、SqlDataReader转实体
说明 使用Expression(表达式目录树)转Entity的文章在园子里有很多,思路也大致也一样,我在前面有篇文章对解决思路有些说明,有兴趣的小伙伴可以看下 (传送门),刚接触表达式目录树时写的,不 ...
- 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句
说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...
- 【手撸一个ORM】第四步、Expression(表达式目录树)扩展
到这里,Orm的基架已经搭起来了,接下来就是激动人心的部分,表达式目录树转Sql语句,SqlDataReader转数据实体等等,但是在这之前,我们需要扩展下表达式目录树的方法,以方便后面的相关操作. ...
- 【手撸一个ORM】第八步、查询工具类
一.实体查询 using MyOrm.Commons; using MyOrm.DbParameters; using MyOrm.Expressions; using MyOrm.Mappers; ...
- 【手撸一个ORM】第二步、封装实体描述和实体属性描述
一.实体属性描述 [MyProperty.cs] Name,属性名称 PropertyInfo,反射获取的属性信息,后面很多地方需要通过该属性获取对应的实体类型,或调用SetValue进行赋值 Fie ...
- 【手撸一个ORM】第三步、SQL语句构造器和SqlParameter封装
既然是数据库工具,自然少不了增删改查的sql语句,在这里将这些常用SQL拼接操作集成到 [SqlServerBuilder.cs] 当中,方便后面调用. 近几年在项目中一直使用Dapper操作数据库, ...
随机推荐
- Redis高可用部署及监控
Redis高可用部署及监控 目录 一.Redis Sentinel简介 二.硬件需求 三.拓扑结构 .单M-S结构 .双M-S结构 .优劣对比 四.配置部 ...
- MySQL常用的数据类型及函数_20160920
1.常用数据类型 针对创建数据表时候 需要指定字段的数据类型,我整理的是工作常用的几种 可以参考看下数据类型 http://www.w3school.com.cn/sql/sql_datatypes. ...
- 高级Java工程师必备 ----- 深入分析 Java IO (一)BIO
BIO编程 最原始BIO 网络编程的基本模型是C/S模型,即两个进程间的通信. 服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可 ...
- Tomcat加载servlet类文件
问题1:tomcat什么时候加载servlet? 有两种情况 一种是启动时加载 一种是请求时加载 第一种是在web.xml中的<servlet>节点下增加类似:<load-on-st ...
- Tomcat加载JSP原理
Tomcat加载JSP主要有以下几个类: JspServlet JspServletWrapper JspCompilationContext JspRuntimeContext JsperLoade ...
- C#如何把XSD中HexBinary类型序列化uint类型
xml schema中有hexBinary类型, 我们在实现C#的Serialization时,一般默认把hexBinary映射为byte[],但是有些情况我们需要把 hexBinary映射为uint ...
- java计算两个时间相差(天、小时、分钟、秒)
public static Long dateDiff(String startTime, String endTime, String format, String str) { // 按照传入的格 ...
- snmp++开发实例一
1.官网下载 snmp开发,首先需要机器已经安装了snmp服务,这方面的资料网上比较完备,安装的时候注意每少一个文件,网上都可以下载到,这样可以自己形成一个包,供以后使用.只要最后snmp的服务开启就 ...
- LINUX socket网络编程
1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 U ...
- C#自定义控件 类似于Linechart
界面效果: 对外提供的属性设置 /// <summary> /// 背景色 /// </summary> public Color BackColor; /// <sum ...