(系列五).net8 中使用Dapper搭建底层仓储连接数据库(附源码)
说明
该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。
该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。
说明:OverallAuth2.0 是一个简单、易懂、功能强大的权限+可视化流程管理系统。
友情提醒:本篇文章是属于系列文章,看该文章前,建议先看之前文章,可以更好理解项目结构。
有兴趣的朋友,请关注我吧(*^▽^*)。

关注我,学不会你来打我
安装Dapper
1、在使用的地方,安装最新版Dapper。
2、在使用的地方,安装最新版的Microsoft.Extensions.Configuration
3、在使用的地方,安装最新版的Microsoft.Extensions.Configuration.Json
4、在使用的地方,安装最新版的System.Data.SqlClient
最终安装包如下:

创建数据库连接类
在创建数据库连接类之前,我们要先在appsettings.json中配置我们的数据库连接字符串。
SqlConnection": "Server=SQLOLEDB;Data Source=你的sqlServer名称;uid=你的数据库账号;pwd=你的数据库密码;DataBase=你的数据库名字
如下图:

配置好数据库连接之后,我们需要一个读取数据库的类,所以我们需要在基础设施层(Infrastructure)创建。
创建文件夹DataBaseConnect然后在创建一个类DataBaseConnectConfig.cs。
内容如下:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System.Data;
using System.Data.SqlClient; namespace Infrastructure.DataBaseConnect
{
/// <summary>
/// 数据库连接类
/// </summary>
public static class DataBaseConnectConfig
{
/// <summary>
/// 声明静态连接
/// </summary>
public static IConfiguration Configuration { get; set; } /// <summary>
/// 静态构造函数
/// </summary>
static DataBaseConnectConfig()
{
//ReloadOnChange = true 当appsettings.json被修改时重新加载
Configuration = new ConfigurationBuilder()
.Add(new JsonConfigurationSource { Path = "appsettings.json", ReloadOnChange = true })
.Build();
} /// <summary>
/// 连接数据库
/// </summary>
/// <param name="sqlConnectionStr">连接数据库字符串</param>
/// <returns></returns>
public static SqlConnection GetSqlConnection(string? sqlConnectionStr = null)
{ if (string.IsNullOrWhiteSpace(sqlConnectionStr))
{
sqlConnectionStr = Configuration["ConnectionStrings:SqlConnection"];
}
var connection = new SqlConnection(sqlConnectionStr);
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
return connection;
}
}
}
GetSqlConnection方法会读取appsettings.json中的连接配置,并打开数据库。
创建仓储
有了数据库连接类后,我们就要开始着手搭建底层仓储,结构如下:

根据以上结构,我们分别创建IRepository.cs仓储接口和Repository.cs仓储接口的实现
IRepository.cs内容如下:
/// <summary>
/// 仓储接口定义
/// </summary>
public interface IRepository
{
}
/// <summary>
/// 定义泛型仓储接口
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <typeparam name="object">主键类型</typeparam>
public interface IRepository<T> : IRepository where T : class, new()
{
/// <summary>
/// 新增
/// </summary>
/// <param name="entity">实体</param>
/// <param name="innserSql">新增sql</param>
/// <returns></returns>
int Insert(T entity, string innserSql); /// <summary>
/// 修改
/// </summary>
/// <param name="entity">实体</param>
/// <param name="updateSql">更新sql</param>
/// <returns></returns>
int Update(T entity, string updateSql); /// <summary>
/// 删除
/// </summary>
/// <param name="deleteSql">删除sql</param>
/// <returns></returns>
int Delete(string key, string deleteSql); /// <summary>
/// 根据主键获取模型
/// </summary>
/// <param name="key">主键</param>
/// <param name="selectSql">查询sql</param>
/// <returns></returns>
T GetByKey(string key, string selectSql); /// <summary>
/// 获取所有数据
/// </summary>
/// <param name="selectAllSql">查询sql</param>
/// <returns></returns>
List<T> GetAll(string selectAllSql); /// <summary>
/// 根据唯一主键验证数据是否存在
/// </summary>
/// <param name="id">主键</param>
/// <param name="selectSql">查询sql</param>
/// <returns>返回true存在,false不存在</returns>
bool IsExist(string id, string selectSql);
说明1:该仓储接口是我们常用的crud(增删改查)的接口,它适用于所有的表结构,让我们不再重复的编写一样的sql语句。
说明2:该仓储接口可以自定义通用的接口,列如分页查询、批量新增、批量修改等。
Repository.cs结构如下
/// <summary>
/// 仓储基类
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <typeparam name="TPrimaryKey">主键类型</typeparam>
public abstract class Repository<T> : IRepository<T> where T : class, new()
{
/// <summary>
/// 删除
/// </summary>
/// <param name="deleteSql">删除sql</param>
/// <returns></returns>
public int Delete(string key, string deleteSql)
{
using var connection = DataBaseConnectConfig.GetSqlConnection();
return connection.Execute(deleteSql, new { Key = key });
} /// <summary>
/// 根据主键获取模型
/// </summary>
/// <param name="id">主键</param>
/// <param name="selectSql">查询sql</param>
/// <returns></returns>
public T GetByKey(string id, string selectSql)
{
using var connection = DataBaseConnectConfig.GetSqlConnection();
return connection.QueryFirstOrDefault<T>(selectSql, new { Key = id });
} /// <summary>
/// 获取所有数据
/// </summary>
/// <param name="selectAllSql">查询sql</param>
/// <returns></returns>
public List<T> GetAll(string selectAllSql)
{
using var connection = DataBaseConnectConfig.GetSqlConnection();
return connection.Query<T>(selectAllSql).ToList();
} /// <summary>
/// 新增
/// </summary>
/// <param name="entity">新增实体</param>
/// <param name="innserSql">新增sql</param>
/// <returns></returns>
public int Insert(T entity, string innserSql)
{
using var connection = DataBaseConnectConfig.GetSqlConnection();
return connection.Execute(innserSql, entity);
} /// <summary>
/// 根据唯一主键验证数据是否存在
/// </summary>
/// <param name="id">主键</param>
/// <param name="selectSql">查询sql</param>
/// <returns>返回true存在,false不存在</returns>
public bool IsExist(string id, string selectSql)
{
using var connection = DataBaseConnectConfig.GetSqlConnection();
var count = connection.QueryFirst<int>(selectSql, new { Key = id });
if (count > 0)
return true;
else
return false;
} /// <summary>
/// 更新
/// </summary>
/// <param name="entity">更新实体</param>
/// <param name="updateSql">更新sql</param>
/// <returns></returns>
public int Update(T entity, string updateSql)
{
using var connection = DataBaseConnectConfig.GetSqlConnection();
return connection.Execute(updateSql, entity);
}
}
该类是IRepository.cs仓储接口的实现,它继承于Repository.cs
创建基础sql仓储(可省略)
做完以上操作,我们的底层仓储事实上已经搭建完成,但博主搭建了一个基础sql的仓储,以便管理项目中所有基础的sql语句。
在Infrastructure的根目录创建一个BaseSqlRepository.cs的类。
编写sql的基础语句,现有语句如下。
/// <summary>
/// 创建继承sql仓储
/// </summary>
public class BaseSqlRepository
{
#region 表Sys_user /// <summary>
/// sys_user新增
/// </summary>
public static string sysUser_insertSql = @"insert into Sys_User (UserName ,Password ,Age,Sex,IsOpen,DepartmentId,CreateTime,CreateUser) values(@UserName ,@Password ,@Age,@Sex,@IsOpen,@DepartmentId,@CreateTime,@CreateUser)"; /// <summary>
/// sys_user更新
/// </summary>
public static string sysUser_updateSql = @"update Sys_User set UserName=@UserName ,Password=@Password ,Age=@Age,Sex=@Sex,DepartmentId=@DepartmentId,CreateTime=@CreateTime,CreateUser=@CreateUser where UserId = @UserId"; /// <summary>
/// sys_user查询
/// </summary>
public static string sysUser_selectByKeySql = @" select * from Sys_User where UserId=@Key"; /// <summary>
/// sys_user表查询全部语句
/// </summary>
public static string sysUser_selectAllSql = @" select * from Sys_User"; #endregion
}
创建表Sys_User模型
结构如下:
/// <summary>
/// 用户表模型
/// </summary>
public class SysUser
{
/// <summary>
/// 用户id
/// </summary>
public int UserId { get; set; } /// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; } /// <summary>
/// 密码
/// </summary>
public string Password { get; set; } /// <summary>
/// 年龄
/// </summary>
public int Age { get; set; } /// <summary>
/// 性别
/// </summary>
public int Sex { get; set; } /// <summary>
/// 是否开启
/// </summary>
public bool IsOpen { get; set; } /// <summary>
/// 部门id
/// </summary>
public int DepartmentId { get; set; } /// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; } /// <summary>
/// 创建人员
/// </summary>
public string CreateUser { get; set; }
}
该结构,同数据库表结构(一会说)
使用仓储
在之前的ISysUserRepository.cs和SysUserRepository.cs中分别继承IRepository.cs 和Repository.cs

/// <summary>
/// 用户服务仓储接口
/// </summary>
public interface ISysUserRepository : IRepository<SysUser>
{
/// <summary>
/// 测试Autofac
/// </summary>
/// <returns></returns>
string TestAutofac();
}
/// <summary>
/// 用户服务仓储接口实现
/// </summary>
public class SysUserRepository : Repository<SysUser>, ISysUserRepository
{
/// <summary>
/// 测试Autofac
/// </summary>
/// <returns></returns>
public string TestAutofac()
{
return "Autofac使用成功";
}
}
该用户仓储继承IRepository.cs 和Repository.cs之后,它就拥有了该仓储接口下的所有接口。
测试
做完以上工作,我们开始测试
首先,我们需要创建数据库(使用sqlServer数据库)和用户表

表结构和数据代码如下:
USE [OverallAuth]
GO
/****** Object: Table [dbo].[Sys_User] Script Date: 2024/10/6 10:38:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Sys_User](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[UserName] [varchar](50) NOT NULL,
[Password] [varchar](50) NOT NULL,
[Age] [int] NULL,
[Sex] [int] NULL,
[DepartmentId] [int] NOT NULL,
[IsOpen] [bit] NULL,
[CreateTime] [datetime] NULL,
[CreateUser] [varchar](50) NULL,
CONSTRAINT [PK_Sys_User] PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Sys_User] ON INSERT [dbo].[Sys_User] ([UserId], [UserName], [Password], [Age], [Sex], [DepartmentId], [IsOpen], [CreateTime], [CreateUser]) VALUES (1, N'张三', N'1', 18, 1, 1, 1, CAST(N'2024-10-06T09:14:13.000' AS DateTime), N'1')
INSERT [dbo].[Sys_User] ([UserId], [UserName], [Password], [Age], [Sex], [DepartmentId], [IsOpen], [CreateTime], [CreateUser]) VALUES (2, N'李四', N'1', 19, 1, 1, 1, CAST(N'2024-10-06T09:15:08.000' AS DateTime), N'1')
SET IDENTITY_INSERT [dbo].[Sys_User] OFF
ALTER TABLE [dbo].[Sys_User] ADD DEFAULT ((0)) FOR [IsOpen]
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户名称' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'UserName'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户密码' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'Password'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户年龄' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'Age'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户年龄 1:男 2:女' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'Sex'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'部门id(表Department主键)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'DepartmentId'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'CreateTime'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建人员' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User', @level2type=N'COLUMN',@level2name=N'CreateUser'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'人员表' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Sys_User'
GO
服务层编写接口调用
说明:以下这些类,都在上一期中有说道,这里不再多说。
/// <summary>
/// 用户服务接口
/// </summary>
public interface ISysUserService
{
/// <summary>
/// 测试Autofac
/// </summary>
/// <returns></returns>
string TestAutofac(); /// <summary>
/// 查询所有用户
/// </summary>
/// <returns></returns>
List<SysUser> GetAllUser();
}
/// <summary>
/// 用户服务接口实现
/// </summary>
public class SysUserService : ISysUserService
{
#region 构造实例化 private readonly ISysUserRepository _sysUserRepository; public SysUserService(ISysUserRepository sysUserRepository)
{
_sysUserRepository = sysUserRepository;
} #endregion /// <summary>
/// 测试Autofac
/// </summary>
/// <returns></returns>
public string TestAutofac()
{
return _sysUserRepository.TestAutofac();
} /// <summary>
/// 查询所有用户
/// </summary>
/// <returns></returns>
public List<SysUser> GetAllUser()
{
return _sysUserRepository.GetAll(BaseSqlRepository.sysUser_selectAllSql);
}
}
在控制器(SysUserController)中添加如下接口
/// <summary>
/// 查询所有用户
/// </summary>
/// <returns></returns>
[HttpGet]
public List<SysUser> GetAllUser()
{
return _userService.GetAllUser();
}
好了,启动项目,进行测试

可以看到,数据获取成功,到这里,我们使用Dapper搭建底层仓储连接数据库成功。
源代码地址:https://gitee.com/yangguangchenjie/overall-auth2.0-web-api
预览地址:http://139.155.137.144:8880/swagger/index.html
帮我Star,谢谢。
有兴趣的朋友,请关注我微信公众号吧(*^▽^*)。

关注我:一个全栈多端的宝藏博主,定时分享技术文章,不定时分享开源项目。关注我,带你认识不一样的程序世界
(系列五).net8 中使用Dapper搭建底层仓储连接数据库(附源码)的更多相关文章
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)
上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...
- arcgis api 3.x for js 入门开发系列批量叠加 zip 压缩 SHP 图层优化篇(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- [五]类加载机制双亲委派机制 底层代码实现原理 源码分析 java类加载双亲委派机制是如何实现的
Launcher启动类 本文是双亲委派机制的源码分析部分,类加载机制中的双亲委派模型对于jvm的稳定运行是非常重要的 不过源码其实比较简单,接下来简单介绍一下 我们先从启动类说起 有一个Lau ...
- vue系列---理解Vue中的computed,watch,methods的区别及源码实现(六)
_ 阅读目录 一. 理解Vue中的computed用法 二:computed 和 methods的区别? 三:Vue中的watch的用法 四:computed的基本原理及源码实现 回到顶部 一. 理解 ...
- 教你搭建SpringMVC框架( 附源码)
一.项目目录结构 二.SpringMVC需要使用的jar包 commons-logging-1.2.jar junit-4.10.jar log4j-api-2.0.2.jar log4j-core- ...
- Springboot系列:Springboot与Thymeleaf模板引擎整合基础教程(附源码)
前言 由于在开发My Blog项目时使用了大量的技术整合,针对于部分框架的使用和整合的流程没有做详细的介绍和记录,导致有些朋友用起来有些吃力,因此打算在接下来的时间里做一些基础整合的介绍,当然,可能也 ...
- JAVA WEB项目中生成验证码及验证实例(附源码及目录结构)
[我是一个初学者,自己总结和网上搜索资料,代码是自己敲了一遍,亲测有效,现将所有的目录结构和代码贴出来分享给像我一样的初学者] 作用 验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计 ...
- 教你搭建SpringSecurity3框架(附源码)
源码下载地址:http://pan.baidu.com/s/1qWsgIg0 一.web.xml <?xml version="1.0" encoding="UTF ...
- leaflet-webpack 入门开发系列二加载不同在线地图切换显示(附源码下载)
前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...
随机推荐
- PixiJS源码分析系列:第四章 响应 Pointer 交互事件(上篇)
响应 Pointer 交互事件(上篇) 上一章我们分析了 sprite 在 canvasRenderer 上的渲染,那么接下来得看看交互上最重要的事件系统了 最简单的 demo 还是用一个最简单的 d ...
- 【Java】Spring注入静态Bean的几种写法
单例模式在Spring注解上的一种拓展用法 写法一,先配置自身Bean,作为静态成员,然后目标Bean作为自身Bean的实例成员' Spring初始化自身Bean时自动装配数据源Bean,从而附属到静 ...
- signal-slot:python版本的多进程通信的信号与槽机制(编程模式)的库(library) —— 强化学习ppo算法库sample-factory的多进程包装器,实现类似Qt的多进程编程模式(信号与槽机制) —— python3.12版本下成功通过测试
什么是 Qt signal-slot库项目地址: https://github.com/alex-petrenko/signal-slot 该库实现的主要原理: 要注意这个项目的library只是对原 ...
- 阿里提供的免费pypi镜像服务器
介绍页地址: https://developer.aliyun.com/mirror/pypi 具体的镜像地址: https://mirrors.aliyun.com/pypi/
- (数据科学学习手札163)ibis:极具潜力的Python数据分析框架
本文完整代码及附件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,今天要给大家介绍的Pyt ...
- MySQL手动执行rollback,内部实现分析
-- 测试手动回滚操作 -- 1手动开启事务 START TRANSACTION -- 2执行更新操作语句 UPDATE FraBakNtuAnalysize SET IsDeleted = 0 WH ...
- SMU Summer 2023 Contest Round 12
SMU Summer 2023 Contest Round 12 A. K-divisible Sum 分类讨论: \(n > k\)时: \(n\)能整除\(k\)就全是\(1\) 不能整除, ...
- c++高效位运算函数之 __builtin_
https://www.cnblogs.com/tldr/p/11288935.html int __builtin_ffs (unsigned int x) 返回x的最后一位1的是从后向前第几位,比 ...
- Atcoder ABC296 F
Atcoder ABC296 F F - Simultaneous Swap 链接: F - Simultaneous Swap (atcoder.jp) 简要题意: 问题陈述 给你两个 \(N\) ...
- Antd-React-TreeSelect前端搜索过滤
在开发过程中,但是antd中的搜索会把多余的也会带出来 就例如下图,我们本想去搜索1但是他会把其子节点都带出来,其实我们的本意是像搜2一样或者当中间隔层处理 但是我们该如何解决这样的问题呢如何做到下面 ...