服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c# 如何自己实现一个ORM框架

c# 如何自己实现一个ORM框架

2022-11-08 12:12月影西下 C#

这篇文章主要介绍了c# 如何自己实现一个ORM,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下

0. 前言

在之前的几篇内容中,我们了解了如何通过ADO.NET 访问数据库,如何修改、新增数据。如何通过DataSet和DataAdapter获取数据,我们将在这一篇试试自己实现一个简单的ORM框架或者说ORM工具类。

涉及到的知识点:

  • 反射(初级)
  • ADO.NET 已有知识

1. ORM

那么,问题来了,什么是ORM?ORM全称 Object Relational Mapping,翻译过来就是对象关系映射。是一种通过描述对象与数据库之间映射关系的数据,将对象保存到数据库中的技术。

在C#中,曾经Entity Framework光芒万丈,遮盖了其他ORM框架的光辉(甚至如今都是如此)。

后来慢慢涌现除了其他的一些ORM框架,进一步丰富了市场。所以现有比较流行的大概有以下几种:

  • Dapper 一个轻量的ORM框架
  • Entity Framework/Entity Framework Core 功能完备的框架
  • Nhibernate Java平台上著名的Hibernate的.net版
  • 等等

嗯,这是我最近找到的创作组还在更新的几个框架,当然还有其他的很多有趣好用的ORM框架。欢迎各位补充哈。

这一篇的主要目的不是介绍这些框架(这是以后的内容),而是通过我们自己实现一个类ORM框架来了解底层核心。

2. 设计

我们先分析一下,如果我们设计一个实体对象与数据库之间转换的工具类应该具有哪些功能?

  • 一个属性与数据库字段的映射关系
  • 增删改查的SQL模板
  • 查询结果与对象的转换

3. 实现

首先,声明一个类,因为不能仅支持一种类型,所以这个类的所有与数据库有关的方法都是泛型方法,或者这个类是泛型类,所以定义为泛型类:

?
1
2
3
public class OrmUtil<T>
{
}

我们事先约定类名即表名,属性名即表的列名,所以我们可以快速得到以下内容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
/// <summary>
/// T的类型实例
/// </summary>
private Type dType;
/// <summary>
/// T的属性表
/// </summary>
private PropertyInfo[] properties;
public OrmUtil()
{
 dType = typeof(T);
 properties = dType.GetProperties();
}

声明一个数据库连接:

?
1
public SqlConnection Connection { get; set; }

创建一个私有方法,检查连接是否可用:

?
1
2
3
4
5
6
7
8
/// <summary>
/// 检查连接是否可用
/// </summary>
/// <returns></returns>
private bool CheckConnection()
{
 return Connection?.State == ConnectionState.Open;
}

准备工作完成,然后开始编写具体的业务方法:

Insert:

?
1
2
3
4
5
6
7
8
9
10
11
12
public int Insert(T entity)
{
 if (!CheckConnection()) return -1;// 检查状态
 var insert = $"insert into {dType.Name}({string.Join(",", properties.Select(t => t.Name))})";
 var values = properties.Select(p => p.GetValue(entity));
 var commandText = $"{insert} values('{string.Join("','", values)}')";
 
 var command = Connection.CreateCommand();
 command.CommandText = commandText;
 var result = command.ExecuteNonQuery();
 return result;
}

首先按照属性名与列名之间的映射拼接 SQL,然后执行SQL命令。

Update:

?
1
2
3
4
5
6
7
8
9
10
public int Update(T entity,string keyName,object keyValue)
{
 if (!CheckConnection()) return -1;
 var setValues = properties.ToDictionary(p => p.Name, p => $"'{p.GetValue(entity)}'");
 var setSql = string.Join(",", setValues.Select(pair=>$"{pair.Key}='{pair.Value}'"));
 var sql = $"update {dType.Name} set {setSql} where {keyName} = '{keyValue}'";
 var command = Connection.CreateCommand();
 command.CommandText = sql;
 return command.ExecuteNonQuery();
}

Update需要注意的就是如何正确拼接赋值sql。

Delete:

删除满足条件的对象:

?
1
2
3
4
5
6
7
8
9
public int Delete(T entity)
{
 if (!CheckConnection()) return -1;
 var querySet = properties.Select(p => $"{p.Name} = '{p.GetValue(entity)}'");
 var sql = $"delete from {dType.Name} where {string.Join(" and ", querySet)}";
 var command = Connection.CreateCommand();
 command.CommandText = sql;
 return command.ExecuteNonQuery();
}

这里写法有时候根据实际业务不同,大多数情况下删除主键对应的元素,或者满足某一个条件的所有元素。这里只是做了个演示,小伙伴们可以试试自己改造一下。

Search:

先创建一个从DataTable转成对象的工具方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private List<T> Convert(DataTable table)
{
 var list = new List<T>(table.Rows.Count);//事先声明一下容量
 foreach(DataRow row in table.AsEnumerable())
 {
  T entity = Activator.CreateInstance<T>();
  foreach(var p in properties)
  {
   if (!table.Columns.Contains(p.Name)) continue;// 如果属性名不在表格中,则忽略
   p.SetValue(entity, row[p.Name]);
  }
  list.Add(entity);
 }
 return list;
}

好,我们写一个查询方法:

?
1
2
3
4
5
6
7
public List<T> SearchAll()
{
 var adapter = new SqlDataAdapter($"select * from {dType.Name}", Connection);
 var set = new DataSet();
 adapter.Fill(set);
 return Convert(set.Tables[0]);
}

这样一个简单的ORM框架就这样形成雏形了,当然实际上的ORM底层比这复杂,因为需要支持不同的数据库,所以Connection 就不能简简单单的是一个SqlConnection了,或者底层不是像我们一样取巧使用DataTable了。

实际上的DataTable到类对象的转换要比我写的复杂一点,因为还要判断这个属性是否是可读、可写的。

4. 总结

在这里我做了个抛砖引玉,带领小伙伴们一起构思了一个简陋的ORM框架,也让大伙对此有了一定的印象。嗯,今天就到这了。同时ADO.NET 也告一段落了,接下来就是上Entity Framework了。当然,DataSet、DataAdapter这两个类并没有讲完。这部分内容可能会在后续的番外篇内补全。

以上就是c# 如何自己实现一个ORM的详细内容,更多关于c# 自己实现一个ORM的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/c7jie/p/12885311.html

延伸 · 阅读

精彩推荐
  • C#c# 使用模式匹配以及 is 和 as 运算符安全地进行强制转换

    c# 使用模式匹配以及 is 和 as 运算符安全地进行强制转换

    这篇文章主要介绍了c# 使用模式匹配以及 is 和 as 运算符安全地进行强制转换,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...

    olprod10712022-10-11
  • C#Unity3D基于OnGUI实时显示FPS

    Unity3D基于OnGUI实时显示FPS

    这篇文章主要介绍了Unity3D基于OnGUI实时显示FPS,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    一缕残阳3472022-08-08
  • C#C#拼图游戏编写代码(2)

    C#拼图游戏编写代码(2)

    这篇文章主要为大家详细介绍了C#拼图游戏的编写代码下篇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    蜡笔小黑8702021-12-31
  • C#详解c# 线程同步

    详解c# 线程同步

    这篇文章主要介绍了c# 线程同步的相关资料,文中讲解非常细致,示例代码帮助大家更好的理解和学习c# 多线程,感兴趣的朋友可以了解下...

    Learning hard4982022-09-29
  • C#C# 模拟浏览器并自动操作的实例代码

    C# 模拟浏览器并自动操作的实例代码

    这篇文章主要介绍了C# 模拟浏览器并自动操作的实例代码,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    Alan.hsiang5042022-09-23
  • C#详解C#正则表达式Regex常用匹配

    详解C#正则表达式Regex常用匹配

    这篇文章主要介绍了C#正则表达式Regex常用匹配,利用Regex类实现验证,感兴趣的小伙伴们可以参考一下...

    柔城9412021-11-05
  • C#C#学习笔记- 随机函数Random()的用法详解

    C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网6102021-12-03
  • C#C#实现过滤sql特殊字符的方法集合

    C#实现过滤sql特殊字符的方法集合

    这篇文章主要介绍了C#实现过滤sql特殊字符的方法,以实例形式分析总结了C#针对SQL危险字符的几种常用的过滤技巧,非常具有实用价值,需要的朋友可以参考下...

    宁静.致远9092021-11-02