【手撸一个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操作数据库, ...
随机推荐
- ECMAScript Obejct 属性操作API
Object 创建对象 我们有很多种方法创建一个对象,Object.create, Object.assign Object.create //字面量 var o = {}; // 等同于 var o ...
- hdu-5802 Windows 10(贪心)
题目链接: Windows 10 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- 基于jQuery Ajax实现无刷新文件上传
最近因项目需求更改,需要实现选择文件后即时上传至服务器,然后提交后,加载xls表格内容到jqgrid表格中,文件上传功能实现示例: 前端jsp页面: <form id="uploadF ...
- Python3解leetcode Best Time to Buy and Sell Stock II
问题描述: Say you have an array for which the ith element is the price of a given stock on day i. Design ...
- 使用EA完成数据库设计
开始重构之后对于EA的了解也逐渐增多,今天就总结一下如何使用EA完成对数据库的设计.下边的图分别是截自机房收费系统和牛腩新闻开发的数据库,因为我第一遍写的时候是在机房合作的时候,而后建立牛腩新闻发布系 ...
- TCP点对点穿透探索--失败
TCP点对点穿透探索 点对点穿透是穿透什么 点对点穿透,需要实现的是对NAT的穿透.想实现NAT的穿透,当然要先了解NAT到底是什么,以及NAT是用来干什么的.NAT全称Network Address ...
- ScrollView cannot scroll in Slidinguppanellayout 解决办法
xml源码如下 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:an ...
- Object中的方法
1.equals() 2.toString() package com_package1; public class Person44 { private int age; public int ge ...
- openstack开发环境搭建
1 目的 让linux下的openstack代码能在windows上面实现同步开发. 2 目标 使用samba实现window与Linux的文件共享. 3 实验环境 ...
- C++ 右值引用与移动操作
右值引用和移动操作是C++11提出的新概念,通过这些操作,可以降低拷贝操作带来的消耗.先来简单介绍一下左值和右值. 左值一般指的是一个对象,或者说是一个持久的值,例如赋值的返回值.下标操作.解引用以及 ...