C#基础系列3:实现自己的ORM…

C#之ORM ORM对象关系映射(Object-Relational Mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。ORM提供了概念性的、易于理解的模型化数据的方式。ORM方法论基于三个核心原则: 简单:以最基本的形式建模数据。 传达性:数据库结构被任何人都能理解的语言文档化。 精确性:基于数据... 阅读详情

构造我自己的ORM

通过前面两章的描述,我相信很多朋友都已经明白我了下面将要讨论到的ORM的实现方法了,那就是根据自定义Attribute来定义O/R Mapping规则,然后通过反射来动态获取此规则,动态构造SQL语句。
由于这个小东西(ORM)出生在深圳,所以我想来想去,她应该有个深圳的名字,所以我就叫她“MiniORM”。不知道各位认为如何?
MiniORM采用的是ONE_INHERIT_TREE_ONE_CLASS(一个继承树对应于一个表)的结构,虽然这种结构容易导致数据冗余,但是这种结构很简单。另,本MiniORM 仅仅考虑一个表一个PK,一个FK的情况。

MiniORM结构如下,为了更便于理解和使用,我使用了3个类:
1、OrmWriter:负责将实体对象(比如前面章节说的Person)插入数据库和修改数据库中对应的记录。
2、OrmRemover:负责根据实体对象,删除指定的记录;
3、OrmReader:负责根据实体对象,读取指定的记录;


上面就是MiniORM的3个主要类。下面我们就详细地根据前面的描述一步步构造她。我们这里还是以前面说的Person为例进行说明。

通过本系列第一章,我们知道,对象不但存在继承关系,特别在实际的应用中还存在包含关系,比如一个Person包含两个Hand(手)类,包含一个Head(头)类等,我们的Person在数据库中应该有一个ID,为了更加方便使用和讨论,此ID在MiniORM中是一个int以及自动增长类型(ID INDENTITY(1,1))。这些都是我们的MiniORM应该考虑的范围。
我们对我们的Person做修改:


[DataObjectAttribute("Person")]
public class Person
{
    private int _ID;
    private string _Name;
    private int _Age;
    private string _Sex;
    private Head _Head;
    private Hand _LeftHand;
    private Hand _RightHand;

    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }

    public Head Head
    {
        get { return _Head; }
        set { _Head = value; }
    }

    public Hand LeftHand
    {
        get { return _LeftHand; }
        set { _LeftHand = value; }
    }

    public Hand RightHand
    {
        get { return _RightHand; }
        set { _RightHand = value; }
    }

    [DataFieldAttribute("name", "NvarChar")]
    public string Name
    {
        get { return this._Name; }
        set { this._Name = value; }
    }

    [DataFieldAttribute("age", "int")]
    public int Age
    {
        get { return this._Age; }
        set { this._Age = value; }
    }

    [DataFieldAttribute("sex", "NvarChar")]
    public string Sex
    {
        get { return this._Sex; }
        set { this._Sex = value; }
    }
}
你可能又发现了一个问题,就是在我们修改后的Person中,增加了LeftHand,RightHand以及Head,可是这三个都属于类啊,这个怎么能够保存到数据库中呢?并且使用我们前面的DataFieldAttribute是没有办法描述的啊。另外还增加了个ID,又怎么来标志这个是自动增长的int型PK呢?当然了能够到这里你就发现这些问题那是相当的不错了。如果前面就动手的人,估计考虑的还是修改我们的DataFieldAttribute让它能够对这些东西进行区别。比如在DataFieldAttribute中再增加一个属性用于区别哪个是ID属性,哪个是对象类型(比如Hand)属性。这当然是好的,只不过这样做导致我们的代码极其丑陋。最好的办法还是另外增加一个Attribute。当然了,我是为了更加方便的构造SQL语句,我做的不是很好。
 
1、怎么表示实体类对应的数据库表的PK和FK?
为了更方便的实现,MiniORM中标志一个实体类的PK和FK都是在DataObjectAttribute中来做(其实最好的办法还是另外增加个比如PKAttribute和FKAttribute,不过这个留给其它人去做吧)。如下,DataObjectAttribute第一个参数表示对应的数据库表,第二个参数表示PK,第三个参数表示FK:


[DataObjectAttribute("Person", "ID", "")]
public class Person
{
    ......
}
2、怎么标志字段是Indentity(自动增长)?
在DataFieldAttribute中增加了个属性,用于标志某个字段是否自动增长的字段。这些都是我个人懒做的,其中,第二个参数标志ID是Identity类型


[DataFieldAttribute("ID", true)]
public int ID
{
    get { return _ID; }
    set { _ID = value; }
}
3、怎样标志字段是类对象(比如Person中的Hand,当然复杂点的对象,可能包含子对象列表)?
由于MiniORM提供的是一个类似框架的东西,所以不应该受到实体类的限制,所以对于类对象字段,我们应该能够描述此对象所在的程序集,命名空间,类名,这样我们才可以运行时创建该对象。


public class SubDataObjectAttribute : Attribute
{
    private SubDataObjectFieldType _FieldType;
    private string _AssemblyName;
    private string _NamespaceName;
    private string _ClassName;

    public SubDataObjectAttribute(SubDataObjectFieldType fieldtype, string assemblyname, string namespacename, string classname)
    {
        this._FieldType = fieldtype;
        this._AssemblyName = assemblyname;
        this._NamespaceName = namespacename;
        this._ClassName = classname;
    }

    /// <summary>
    /// 本记录对应的FieldType
    /// </summary>
    public SubDataObjectFieldType FieldType
    {
        get { return _FieldType; }
    }

    /// <summary>
    /// 本记录对应的AssemblyName
    /// </summary>
    public string AssemblyName
    {
        get { return _AssemblyName; }
    }

    /// <summary>
    /// 本记录对应的NamespaceName
    /// </summary>
    public string NamespaceName
    {
        get { return _NamespaceName; }
    }

    /// <summary>
    /// 本记录对应的ClassName
    /// </summary>
    public string ClassName
    {
        get { return _ClassName; }
    }
}
 

其中SubDataObjectFieldType是一个枚举类型,因为我们的子对象可能是单独的对象比如Person.Head也可能是一个列表(List)。所以我增加了这个枚举类型,用于做标志。

public enum SubDataObjectFieldType
{
    Object,
    /// <summary>
    /// 本字段属于List类型,直接遍历
    /// </summary>
    List,
}
当然了,这里的子对象列表可能是ArrayList,HashTable等等,你都可以根据自己项目中实际使用到的类型来做相应的修改。

4、怎么控制某个字段在表中不能重复?
比如我们要控制Person.Name不能重复,如果你新增的时候发现重复要提示。那我们也通过增加一个Attribute的形式来实现。这个Attribute很简单,没有任何方法和属性。


public class DataFieldNotDoubleAttribute : Attribute
{
}
 

5、怎样做事务处理?
事务处理是每个底层框架都应该考虑到的问题,在.NET中我们有两种方式来进行事务处理,一种是使用COM+,这是最好的方法,不过性能上比较欠缺,另外这东西配置很麻烦,当你数据库安装在另外一太服务器上的时候,往往出现无法使用的问题,我曾经就被这东西折腾够呛,所以我干脆就不用他了,不过还是介绍下语法,通过使用TransactionScope就可以很好的使用com+提供的事务处理,代码相当的简洁,优美,只可惜啊!天使的面孔,魔鬼的心。


public void function1()
{
    using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required))
    {
        function2();
    }
}

public void function2()
{
    using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required))
    {
        //DoSomething();
    }
}
另外一种方法就是使用SqlTransaction:

 

using (SqlConnection conn = new SqlConnection(ConnectionStr))
{
    conn.Open();
    SqlTransaction trans = conn.BeginTransaction();
    //DoSomething(); 
    trans.Commit();
}
不过遗憾的是这种方式不能实现事务嵌套,所以只能通过将trans作为参数进行传递来实现事务处理。

经过上面一系列的修改后,我们的Person成了什么样子了?


[DataObjectAttribute("Person", "ID", "")]
public class Person
{
    private int _ID;
    private string _Name;
    private int _Age;
    private string _Sex;
    private Head _Head;
    private Hand _LeftHand;
    private Hand _RightHand;

    [DataFieldAttribute("ID", true)]
    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }

    [SubDataObjectAttribute(SubDataObjectFieldType.Object, "Person", "Person", "Head")]
    public Head Head
    {
        get { return _Head; }
        set { _Head = value; }
    }

    [SubDataObjectAttribute(SubDataObjectFieldType.Object, "Person", "Person", "Hand")]
    public Hand LeftHand
    {
        get { return _LeftHand; }
        set { _LeftHand = value; }
    }

    [SubDataObjectAttribute(SubDataObjectFieldType.Object, "Person", "Person", "Hand")]
    public Hand RightHand
    {
        get { return _RightHand; }
        set { _RightHand = value; }
    }

    [DataFieldAttribute("name", "NvarChar")]
    public string Name
    {
        get { return this._Name; }
        set { this._Name = value; }
    }

    [DataFieldAttribute("age", "int")]
    public int Age
    {
        get { return this._Age; }
        set { this._Age = value; }
    }

    [DataFieldAttribute("sex", "NvarChar")]
    public string Sex
    {
        get { return this._Sex; }
        set { this._Sex = value; }
    }
}


当然了对于Person这样的实体类,我们完全可以自己写代码自动生成工具来弄,然后再做很小的修改就可以了,这样的工具实现简单,我就不讨论了。
好了,关于我的MiniORM我就讨论到这里了,其它的请看代码吧。

ORM虽然是好东西,但是也存在很多方面的不足,首先我们能够做到的是将大部分的数据库操作交个ORM来做。另外少部分还是需要我们自己写SQL的。单大部分的工作的分离可以为我们节约大量的时间(也就是所谓的20/80原则,80%的教给ORM来处理,20%的自己做,当然很好了)。另外通过将这些相同的流程教给ORM来处理,可以避免很多的疏忽导致的失误(比如不小心把某个Insert,Update,Delete语句弄错了什么的)。
最主要的缺点当然是性能问题,特别是我的MiniORM,全部采用反射来获取映射规则,从而导致性能上更多的下降,不过我们了解方法以后是很容易通过动态生成代码,动态编译的方式来减少这部分的性能损失的。另外某些部分的代码显得有些臃肿,特别是把判断是否Indentity这样的代码放DataFieldAttribute中来处理(这个完全可以象DataFieldNotDoubleAttribute一分开处理的样)等等。

 

C#学习笔记 使用ORM框架SqlSugar 由果糖团队维护的一款开源DotNet ORM框架SqlSugar .Net ORM 5.X 官网 、文档、教程 - SqlSugar 5x - .NET果糖网 (donet5.com) 阅读详情

相关推荐

C#进阶:轻量级ORM框架Dapper详解

Dapper是一个轻量级、高性能的.NET ORM工具,它允许开发者直接编写SQL语句并映射到.NET对象。通过提供简单的API和高效的性能,Dapper成为许多.NET开发者的首选ORM之一。然而,它也有一些局限性,如缺乏内置的高级功能和SQL依赖等。在使用Dapper时,建议结合项目需求、数据库环境和开发团队的经验来评估其适用性,并考虑使用插件和扩展来增强其功能。同时,也需要注意SQL注入的风险,并确保编写高效的SQL查询和合理的数据库操作。

陈辰学长的博客 5902

C#中的ORM框架

1. 什么是ORM ORM:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping) 用于实现面向对象编程语言里不同类型系统的数据之间的转换 ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射 ORM可以解决数据库与程序间的异构性,比如:在C#中我们使用string表示字符串,而Oracle中可使用varchar2,MySQL中可使用varchar,SQLServer可使用nvarchar。 如果没有ORM我们原始

XiaoCai 9514

一个C#的ORM框架

一个自己写的ORM框架,做了一些连接池和OR映射的功能, 测试效率还行,详情见http://blog.youkuaiyun.com/shmilyhe/archive/2009/09/07/4526191.aspx 暂时只支持SQL SERVER 和MYSQL 晚些会上传一些DEMO

C#ORM(关系对象映射)的框架

一、关于ORM ORM的概念: 对象关系映射(Object Relationsl Mapping,简称ORM,或O/RM,或O/R mapping),是一种技术,用于实现面向对象编程语言里不同类型系统数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。 ORM的优势:实现快速开发,方便移植数据库。 .NET开发中的ORM框架: NHibernate 、MyBatis.NET 、LINQ to SQL(已经不再使用) 、 ADO.NET Entity Frame..

weixin_44548405的博客 5994

Livox MID360与Fast-LIO2的实战部署指南:从驱动安装到点云处理

本文提供Livox MID360激光雷达与Fast-LIO2激光惯性里程计从零开始的实战部署指南。详细介绍了Ubuntu系统下的驱动安装、网络配置、点云数据验证以及Fast-LIO2算法的编译、参数配置与联合启动流程,帮助开发者快速搭建移动机器人SLAM系统,并包含关键参数调优与常见故障排查方法。

java5的博客 1024

电信天翼云OS(ctyunos)内网离线安装Docker-CE保姆级避坑指南(附完整依赖包清单)

本文提供电信天翼云OS(ctyunos)内网环境下Docker-CE的离线安装全攻略,涵盖依赖分析、离线包制备、冲突解决等关键步骤。针对金融、政务等隔离网络场景,详细解析如何通过本地仓库构建和优化配置,实现高效安全的容器化部署,助力企业快速搭建内网Docker环境。

397

C#基础系列:实现自己的ORM(ORM的基础概念)

【转 http://blog.youkuaiyun.com/ronotian/article/details/2900698】 ORM(O/R Mappping对象关系映射)的基础概念 在我们的系统中,存在大量的需要进行持久化存储的对象,这些对象可能是各种各样的业务单据,也可能是我们的系统配置信息等。另外一些属于内存中使用而不需要进行持久化存储的对象,不属于我们的讨论范围。而在支持对象序列化的语言...

weixin_30312563的博客 515

CGNS快速入门到实战(一):CGNS静态链接库编译

近期,由于需要将CGNS格式加入到教研组自编CFD求解器DUBHE中,所以本人展开了对于CGNS的学习。CGNS快速入门到实战这一系列分成三篇文章展开叙述,具体有:(一)CGNS静态链接库编译;(二)VS配置调用CGNS静态链接库编写;(三)CGNS文件及案例展示。本篇文章重点讲述CGNS静态链接库编译。

ahang_99的博客 3819

C#基础系列1:实现自己的ORM…

原文地址:C#基础系列1:实现自己的ORM(ORM的基础概念)【转】作者:YouthWithYouthORM(O/R Mappping对象关系映射)的基础概念   在我们的系统中,存在大量的需要进行持久化存储的对象,这些对象可能是各种各样的业务单据,也可能是我们的系统配置信息等。另外一些属于内存中使用而不需要进行持久化存储的对象,不属于我们的讨论范围。而在支持对象序列化的语言比如C#,Java中

绝凌峰 2393

贴片二极管SOD封装详解:SOD-123/323/523尺寸焊盘设计要点

表面贴装技术中,二极管封装尺寸直接决定PCB布局与焊接可靠性。SOD封装作为小外形二极管的主流形态,其SOD-123、SOD-323、SOD-523三种规格分别对应不同的功耗与占板面积权衡。理解封装尺寸、焊盘设计计算逻辑和钢网开窗原理,是避免立碑、虚焊等工艺缺陷的关键。在可穿戴设备、电源保护等空间受限场景中,合理选择封装不仅能优化散热路径,还能提升量产良率。本文从焊盘计算、工艺要点到选型策略,全面解析SOD封装的工程实践。

weixin_42520780的博客 302

软件崩溃时Visual Studio中看不到有效的调用堆栈,使用Windbg动态调试去分析定位

当在Visual Studio中遇到软件崩溃且无法查看详细调用堆栈时,可以使用Windbg进行动态调试去分析定位问题。

dvlinker的技术专栏 1万+

C#基础系列:实现自己的ORM(构造我自己的ORM)

【转 http://blog.youkuaiyun.com/ronotian/article/details/2900734】 构造我自己的ORM 通过前面两章的描述,我相信很多朋友都已经明白我了下面将要讨论到的ORM的实现方法了,那就是根据自定义Attribute来定义O/R Mapping规则,然后通过反射来动态获取此规则,动态构造SQL语句。 由于这个小东西(ORM)出生在深圳,所以我想来想去...

weixin_30786617的博客 252

[游戏排查] Baldur‘s Gate 3 加载完成即崩溃?五步排查帮你快速定位问题

《博德之门3》加载崩溃问题解决方案:针对游戏进度条走完后闪退的情况,提供五步排查法。首先清除LevelCache缓存(成功率最高),其次检查Mod兼容性,然后切换Vulkan/DX11渲染API,再排查存档损坏问题,最后可删除配置目录(需备份存档)。重点提示Steam验证无法解决此类问题,建议按步骤顺序排查,多数情况下前两步即可解决问题。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 3261

C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)

反射以及Attribute在ORM中的应用 一、反射什么是反射?简单点吧,反射就是在运行时动态获取对象信息的方法,比如运行时知道对象有哪些属性,方法,委托等等等等。反射有什么用呢?反射不但让你在运行是获取对象的信息,还提供运行时动态调用对象方法以及动态设置、获取属性等的能力。反射在ORM中有什么用呢?我这里所讨论的ORM实现是通过自定义Attribute的方式进行映射规则的描述的。但...

weixin_34179762的博客 319

Cesium 实现动态加载气象数据:渲染成动态雨雪/云层效果(源码 + 原理)

本文介绍了在Cesium中实现动态天气效果的技术方案。核心思路是通过时间轴驱动多层数据动态切换,包括:1)时间维度处理,按序列加载不同气象图层;2)空间维度处理,将气象数据切分为瓦片;3)效果层实现,制作风场、降水等动态可视化效果。文章详细讲解了后端数据预处理(生成瓦片和风场JSON)、前端实现(双层雷达瓦片交替渐变、风场粒子系统)的具体方法,并提供了完整的代码示例。此外还探讨了雨雪粒子、云层效果等增强功能,以及工程化建议,为构建科学准确的动态天气可视化系统提供了实用解决方案。

专注AI大模型,软件混淆,授权 623

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C# 数据操作系列 - 4. 自己实现一个ORM

0. 前言 在之前的几篇内容中,我们了解了如何通过ADO.NET 访问数据库,如何修改、新增数据。如何通过DataSet和DataAdapter获取数据,我们将在这一篇试试自己实现一个简单的ORM框架或者说ORM工具类。 涉及到的知识点: 反射(初级) ADO.NET 已有知识 1. ORM 那么,问题来了,什么是ORM?ORM全称 Object Relational Mapping,翻译过来就是对象关系映射。是一种通过描述对象与数据库之间映射关系的数据,将对象保存到数据库中的技术。 在C#中,曾经En

菜鸡成长日记 1254

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

orm框架有哪些_C# 数据操作系列 - 4. 自己实现一个ORM

0. 前言 在之前的几篇内容中,我们了解了如何通过http://ADO.NET 访问数据库,如何修改、新增数据。如何通过DataSet和DataAdapter获取数据,我们将在这一篇试试自己实现一个简单的ORM框架或者说ORM工具类。 涉及到的知识点: 反射(初级) http://ADO.NET 已有知识 1. ORM 那么,问题来了,什么是ORM?ORM全称 Object Relational...

weixin_39728213的博客 591

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

c# list 容量_C# 数据操作系列 - 4. 自己实现一个ORM

0. 前言在之前的几篇内容中,我们了解了如何通过ADO.NET 访问数据库,如何修改、新增数据。如何通过DataSet和DataAdapter获取数据,我们将在这一篇试试自己实现一个简单的ORM框架或者说ORM工具类。涉及到的知识点:反射(初级)ADO.NET 已有知识1. ORM那么,问题来了,什么是ORM?ORM全称 Object Relational Mapping,翻译过来就是对象关系映射...

weixin_30819373的博客 125
上一篇: VS快捷键
下一篇: C#基础系列2:反射以及Attri…
绝凌峰
博客等级 码龄18年 28粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值