【手撸一个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操作数据库, ...
随机推荐
- enable nested VT in VM
问题描述: 处理器支持VT-x,并且已经在BIOS中开启了VT-x.在host os上用VMware Workstation安装了一个Ubuntu虚拟机,在虚拟机中执行“cat /proc/cpuin ...
- OpenCV——PS滤镜 漩涡 vertex
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...
- ACM学习历程—HDU 1272 小希的迷宫(并查集)
Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就 ...
- finetune
微调的具体方法和技巧有很多种,这里总结了在不同场景下的微调技巧: 1)新数据集比较小且和原数据集相似.因为新数据集比较小(比如<5000),如果fine-tune可能会过拟合:又因为新旧数据集类 ...
- ContextMenu的自定义
1.针对整个ContextMenu, 自定义一个Style,去掉竖分割线 <Style x:Key="DataGridColumnsHeaderContextMenuSty ...
- nagios客户端安装与配置windows篇
一.被监控的windows xp客户端的配置 1.安装NSClient++并安装下载地址: http://sourceforge.net/projects/nscplusNSClient++-0.3. ...
- Linux 包管理基础:apt、yum、dnf 和 dpkg
https://linux.cn/article-8782-1.html 1. apt-get 安装( 在线) 会帮我把所有的依赖包都一起安装 apt-get install xxx 安装xxx .如 ...
- 转载:数据库应用开发工具Toad使用笔记
由于网上TOAD中文教程很少,在网上摘抄了此文章便于学习,感谢原创者. TOAD使用笔记 1.把鼠标停在sql所在行,然后ctrl+Enter直接执行当前sql. 2.解决Toad对中文显示乱码问题( ...
- css水平居中方式
1. text-align:center 这种方式只适合于内联元素或者文字处于块元素当中是,给块元素设置这个,那么块元素当中的文字或者内联元素则居中.兼容各种浏览器 <div class=&qu ...
- Redux API之creatStore
createStore(reducer, [initialState]) 创建一个 Redux store 来以存放应用中所有的 state.应用中应有且仅有一个 store. 参数 reducer ...