前言
我可能有三年没怎么碰C#了,目前的工作是在全职搞前端,最近有时间抽空看了一下Asp.net Core,Core版本号都到了5.0了,也越来越好用了,下面将记录一下这几天以来使用Asp.Net Core WebApi+Dapper+Mysql+Redis+Docker的一次开发过程。
项目结构
最终项目结构如下,CodeUin.Dapper数据访问层,CodeUin.WebApi应用层,其中涉及到具体业务逻辑的我将直接写在Controllers中,不再做过多分层。CodeUin.Helpers我将存放一些项目的通用帮助类,如果是只涉及到当前层的帮助类将直接在所在层级种的Helpers文件夹中存储即可。
安装环境
MySQL
# 下载镜像
docker pull mysql
# 运行
docker run -itd --name 容器名称 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=你的密码 mysql
如果正在使用的客户端工具连接MySQL提示1251,这是因为客户端不支持新的加密方式造成的,解决办法如下。
# 查看当前运行的容器
docker ps
# 进入容器
docker exec -it 容器名称 bash
# 访问MySQL
mysql -u root -p
# 查看加密规则
select host,user,plugin,authentication_string from mysql.user;
# 对远程连接进行授权
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
# 更改密码加密规则
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';
# 刷新权限
flush privileges;
最后,使用MySQL客户端工具进行连接测试,我使用的工具是Navicat Premium。
Redis
# 下载镜像
docker pull redis
# 运行
docker run -itd -p 6379:6379 redis
使用Redis客户端工具进行连接测试,我使用的工具是Another Redis DeskTop Manager。
.NET 环境
服务器我使用的是CentOS 8,使用的NET SDK版本5.0,下面将记录我是如何在CentOS 8中安装.NET SDK和.NET运行时的。
# 安装SDK
sudo dnf install dotnet-sdk-5.0
# 安装运行时
sudo dnf install aspnetcore-runtime-5.0
检查是否安装成功,使用dotnet --info
命令查看安装信息
创建项目
下面将实现一个用户的登录注册,和获取用户信息的小功能。
数据服务层
该层设计参考了 玉龙雪山 的架构,我也比较喜欢这种结构,一看结构就知道是要做什么的,简单清晰。
首先,新建一个项目命名为CodeUin.Dapper,只用来提供接口,为业务层服务。
- Entities
- 存放实体类
- IRepository
- 存放仓库接口
- Repository
- 存放仓库接口实现类
- BaseModel
- 实体类的基类,用来存放通用字段
- DataBaseConfig
- 数据访问配置类
- IRepositoryBase
- 存放最基本的仓储接口 增删改查等
- RepositoryBase
- 基本仓储接口的具体实现
创建BaseModel基类
该类存放在项目的根目录下,主要作用是将数据库实体类中都有的字段独立出来。
using System;
namespace CodeUin.Dapper
{
/// <summary>
/// 基础实体类
/// </summary>
public class BaseModel
{
/// <summary>
/// 主键Id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
}
}
创建DataBaseConfig类
该类存放在项目的根目录下,我这里使用的是MySQL,需要安装以下依赖包,如果使用的其他数据库,自行安装对应的依赖包即可。
该类具体代码如下:
using MySql.Data.MySqlClient;
using System.Data;
namespace CodeUin.Dapper
{
public class DataBaseConfig
{
private static string MySqlConnectionString = @"Data Source=数据库地址;Initial Catalog=codeuin;Charset=utf8mb4;User ID=root;Password=数据库密码;";
public static IDbConnection GetMySqlConnection(string sqlConnectionString = null)
{
if (string.IsNullOrWhiteSpace(sqlConnectionString))
{
sqlConnectionString = MySqlConnectionString;
}
IDbConnection conn = new MySqlConnection(sqlConnectionString);
conn.Open();
return conn;
}
}
}
创建IRepositoryBase类
该类存放在项目的根目录下,存放常用的仓储接口。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CodeUin.Dapper
{
public interface IRepositoryBase<T>
{
Task<int> Insert(T entity, string insertSql);
Task Update(T entity, string updateSql);
Task Delete(int Id, string deleteSql);
Task<List<T>> Select(string selectSql);
Task<T> Detail(int Id, string detailSql);
}
}
创建RepositoryBase类
该类存放在项目的根目录下,是IRepositoryBase类的具体实现。
using Dapper;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
namespace CodeUin.Dapper
{
public class RepositoryBase<T> : IRepositoryBase<T>
{
public async Task Delete(int Id, string deleteSql)
{
using (IDbConnection conn = DataBaseConfig.GetMySqlConnection())
{
await conn.ExecuteAsync(deleteSql, new { Id });
}
}
public async Task<T> Detail(int Id, string detailSql)
{
using (IDbConnection conn = DataBaseConfig.GetMySqlConnection())
{
return await conn.QueryFirstOrDefaultAsync<T>(detailSql, new { Id });
}
}
public async Task<List<T>> ExecQuerySP(string SPName)
{
using (IDbConnection conn = DataBaseConfig.GetMySqlConnection())
{
return await Task.Run(() => conn.Query<T>(SPName, null, null, true, null, CommandType.StoredProcedure).ToList());
}
}
public async Task<int> Insert(T entity, string insertSql)
{
using (IDbConnection conn = DataBaseConfig.GetMySqlConnection())
{
return await conn.ExecuteAsync(insertSql, entity);
}
}
public async Task<List<T>> Select(string selectSql)
{
using (IDbConnection conn = DataBaseConfig.GetMySqlConnection())
{
return await Task.Run(() => conn.Query<T>(selectSql).ToList());
}
}
public async Task Update(T entity, string updateSql)
{
using (IDbConnection conn = DataBaseConfig.GetMySqlConnection())
{
await conn.ExecuteAsync(updateSql, entity);
}
}
}
}
好了,基础类基本已经定义完成。下面将新建一个Users类,并定义几个常用的接口。
创建Users实体类
该类存放在Entities文件夹中,该类继承BaseModel。
namespace CodeUin.Dapper.Entities
{
/// <summary>
/// 用户表
/// </summary>
public class Users : BaseModel
{
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
/// <summary>
/// 盐
/// </summary>
public string Salt { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; }
/// <summary>
/// 手机号
/// </summary>
public string Mobile { get; set; }
/// <summary>
/// 性别
/// </summary>
public int Gender { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
/// <summary>
/// 头像
/// </summary>
public string Avatar { get; set; }
/// <summary>
/// 是否删除
/// </summary>
public int IsDelete { get; set; }
}
}
创建IUserRepository类
该类存放在IRepository文件夹中,继承IRepositoryBase,并定义了额外的接口。
using CodeUin.Dapper.Entities;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CodeUin.Dapper.IRepository
{
public interface IUserRepository : IRepositoryBase<Users>
{
Task<List<Users>> GetUsers();
Task<int> AddUser(Users entity);
Task DeleteUser(int d);
Task<Users> GetUserDetail(int id);
Task<Users> GetUserDetailByEmail(string email);
}
}
创建UserRepository类
该类存放在Repository文件夹中,继承RepositoryBase, IUserRepository ,是IUserRepository类的具体实现。