ASP.NET Core:使用Dapper和SwaggerUI来丰富你的系统框架
分类:
IT文章
•
2024-02-20 17:26:30
一、概述
1、用VS2017创建如下图的几个.NET Standard类库,默认版本为1.4,你可以通过项目属性进行修改,最高支持到1.6,大概五月份左右会更新至2.0,API会翻倍,很期待!
 |
排名分先后,这里简要说下我对各个类库职责的一个理解。
- Light.Model:存放实际项目中你用到的所有实体集合,包括数据库表映射实体,请求实体,响应实体,视图显示实体以及一些公共实体类等,同时你还可以根据自己业务的模块功能进行更细致的划分。
- Light.IRepository:数据库仓储接口,定义你操作数据库的所有动作,包括简单的C(Create)R(Retrive)U(Update)D(Delete),也就是我们经常说的增查改删。对于上层服务而言,我只要暴露出来操作数据库的接口就可以了,而不需要关注具体的实现,这样一来,不管我使用Dapper还是EF Core,抑或是SQLServer或者MySql,对调用者来说,不会有任何影响。
- Light.Repository:各种请求数据库数据的方法都在这里,你可以选择自己喜欢的工具,自己喜欢的语言来丰富它,sql也好,linq也罢,只要你高兴,随时可以搞起来。
- Light.IBusiness和Light.Business:业务逻辑接口定义和实现,理解了上面说的, 这两层其实含义是差不多的。复杂的业务逻辑,验证或者判断等等,你都在Business里边实现好,至于以后是web api来调用还是普通的web来调用,这些都交由IBusiness来做就可以了
- Light.DependencyInjection:依赖注入。从此解放我们的双手,再也不用new来new去了,代码也整洁了,同时也解耦了,况且它已经被集成到.net core中,何乐而不为呢。
- 那么剩下如果后续有需要Common层或者Web层的,向解决方案里边添加就好,这俩就不用过多解释什么了,你懂的
|
2、当然了,你还可以通过.NET Core Tool的cli命令来创建,前提是你的电脑上安装了.NET Core SDK。
dotnet new classlib -n Light.Repository //创建一个名字为Light.Repository的.NET Standard类库
更多创建类型请键入如下命令进行查看

红框内自上而下依次表示:
- 控制台应用程序
- 类库
- 微软自带的单元测试项目
- 引入XUnit框架的单元测试项目
- 空的ASP.NET Core
- ASP.NET Core MVC项目
- ASP.NET Core WebAPI项目
- 空的解决方案
二、引入Dapper
1、准备创建用户表的SQL脚本
1 USE [Light]
2 GO
3
4 /****** Object: Table [dbo].[User] Script Date: 2017/3/27 22:40:08 ******/
5 SET ANSI_NULLS ON
6 GO
7
8 SET QUOTED_IDENTIFIER ON
9 GO
10
11 CREATE TABLE [dbo].[User](
12 [Id] [int] IDENTITY(10000,1) NOT NULL,
13 [UserName] [nvarchar](50) NOT NULL,
14 [Password] [nvarchar](50) NOT NULL,
15 [Gender] [bit] NOT NULL,
16 [Birthday] [datetime] NOT NULL,
17 [CreateUserId] [int] NOT NULL,
18 [CreateDate] [datetime] NOT NULL,
19 [UpdateUserId] [int] NOT NULL,
20 [UpdateDate] [datetime] NOT NULL,
21 [IsDeleted] [bit] NOT NULL,
22 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
23 (
24 [Id] ASC
25 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
26 ) ON [PRIMARY]
27
28 GO
29
30 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_UserName] DEFAULT ('') FOR [UserName]
31 GO
32
33 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_Password] DEFAULT ('') FOR [Password]
34 GO
35
36 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_Gender] DEFAULT ((0)) FOR [Gender]
37 GO
38
39 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_Birthday] DEFAULT (getdate()) FOR [Birthday]
40 GO
41
42 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_CreateUserId] DEFAULT ((0)) FOR [CreateUserId]
43 GO
44
45 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_CreateDate] DEFAULT (getdate()) FOR [CreateDate]
46 GO
47
48 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_UpdateUserId] DEFAULT ((0)) FOR [UpdateUserId]
49 GO
50
51 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_UpdateDate] DEFAULT (getdate()) FOR [UpdateDate]
52 GO
53
54 ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
55 GO
56
57 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键Id' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'Id'
58 GO
59
60 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'用户名' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'UserName'
61 GO
62
63 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'密码' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'Password'
64 GO
65
66 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'性别(0女,1男)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'Gender'
67 GO
68
69 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'出生年月日' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'Birthday'
70 GO
71
72 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建人' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'CreateUserId'
73 GO
74
75 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'CreateDate'
76 GO
77
78 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'更新人' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'UpdateUserId'
79 GO
80
81 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'更新时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'UpdateDate'
82 GO
83
84 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'标志是否删除(0未删除,1已删除)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'User', @level2type=N'COLUMN',@level2name=N'IsDeleted'
85 GO
View Code
2、添加对应的User表实体
1 /// <summary>
2 /// 用户实体
3 /// </summary>
4 public class User : BaseModel
5 {
6 /// <summary>
7 /// 用户名
8 /// </summary>
9 public string UserName { get; set; }
10
11 /// <summary>
12 /// 密码
13 /// </summary>
14 public string Password { get; set; }
15
16 /// <summary>
17 /// 性别(0女,1男)
18 /// </summary>
19 public bool Gender { get; set; }
20
21 /// <summary>
22 /// 出生年月日
23 /// </summary>
24 public DateTime Birthday { get; set; }
25 }
View Code
3、使用泛型针对每一个表定义基本的CRUD接口,然后IUserRepository继承它,如果需要其他的接口,后续往里边定义即可
1 /// <summary>
2 /// 基类业务接口定义
3 /// </summary>
4 public interface IBaseBusiness<T> where T : class
5 {
6 /// <summary>
7 /// 添加一个实体
8 /// </summary>
9 /// <param name="entity">要创建的实体</param>
10 /// <param name="connectionString">链接字符串</param>
11 /// <returns></returns>
12 bool CreateEntity(T entity, string connectionString = null);
13
14 /// <summary>
15 /// 根据主键Id获取一个实体
16 /// </summary>
17 /// <param name="id">主键Id</param>
18 /// <param name="connectionString">链接字符串</param>
19 /// <returns></returns>
20 T RetriveOneEntityById(int id, string connectionString = null);
21
22 /// <summary>
23 /// 获取所有实体
24 /// </summary>
25 /// <param name="connectionString">链接字符串</param>
26 /// <returns></returns>
27 IEnumerable<T> RetriveAllEntity(string connectionString = null);
28
29 /// <summary>
30 /// 修改一个实体
31 /// </summary>
32 /// <param name="entity">要修改的实体</param>
33 /// <param name="connectionString">链接字符串</param>
34 /// <returns></returns>
35 bool UpdateEntity(T entity, string connectionString = null);
36
37 /// <summary>
38 /// 根据主键Id删除一个实体
39 /// </summary>
40 /// <param name="id">主键Id</param>
41 /// <param name="connectionString">链接字符串</param>
42 /// <returns></returns>
43 bool DeleteEntityById(int id, string connectionString = null);
44 }
View Code
4、主角进场。通过Nuget引入Dapper到Repository中,目前的版本为1.50.2
a)、设置你的链接字符串和DbConnection
1 /// <summary>
2 /// 数据库配置
3 /// </summary>
4 public class DataBaseConfig
5 {
6 #region SqlServer链接配置
7 /// <summary>
8 /// 默认的Sql Server的链接字符串
9 /// </summary>
10 private static string DefaultSqlConnectionString = @"Data Source=.;Initial Catalog=Light;User ID=sa;Password=sa;";
11 public static IDbConnection GetSqlConnection(string sqlConnectionString = null)
12 {
13 if (string.IsNullOrWhiteSpace(sqlConnectionString))
14 {
15 sqlConnectionString = DefaultSqlConnectionString;
16 }
17 IDbConnection conn = new SqlConnection(sqlConnectionString);
18 conn.Open();
19 return conn;
20 }
21 #endregion
22 }
b)、实现IUserRepository定义的接口,使用Dapper进行操作数据
1 /// <summary>
2 /// 用户仓储
3 /// </summary>
4 /// <typeparam name="User"></typeparam>
5 public class UserRepository : IUserRepository
6 {
7 /// <summary>
8 /// 创建一个用户
9 /// </summary>
10 /// <param name="entity">用户</param>
11 /// <param name="connectionString">链接字符串</param>
12 /// <returns></returns>
13 public bool CreateEntity(User entity, string connectionString = null)
14 {
15 using (IDbConnection conn = DataBaseConfig.GetSqlConnection(connectionString))
16 {
17 string insertSql = @"INSERT INTO [dbo].[User]
18 ([UserName]
19 ,[Password]
20 ,[Gender]
21 ,[Birthday]
22 ,[CreateUserId]
23 ,[CreateDate]
24 ,[UpdateUserId]
25 ,[UpdateDate]
26 ,[IsDeleted])
27 VALUES
28 (@UserName
29 ,@Password
30 ,@Gender
31 ,@Birthday
32 ,@CreateUserId
33 ,@CreateDate
34 ,@UpdateUserId
35 ,@UpdateDate
36 ,@IsDeleted)";
37 return conn.Execute(insertSql, entity) > 0;
38 }
39 }
40
41 /// <summary>
42 /// 根据主键Id删除一个用户
43 /// </summary>
44 /// <param name="id">主键Id</param>
45 /// <param name="connectionString">链接字符串</param>
46 /// <returns></returns>
47 public bool DeleteEntityById(int id, string connectionString = null)
48 {
49 using (IDbConnection conn = DataBaseConfig.GetSqlConnection(connectionString))
50 {
51 string deleteSql = @"DELETE FROM [dbo].[User]
52 WHERE Id = @Id";
53 return conn.Execute(deleteSql, new { Id = id }) > 0;
54 }
55 }
56
57 /// <summary>
58 /// 获取所有用户
59 /// </summary>
60 /// <param name="connectionString">链接字符串</param>
61 /// <returns></returns>
62 public IEnumerable<User> RetriveAllEntity(string connectionString = null)
63 {
64 using (IDbConnection conn = DataBaseConfig.GetSqlConnection(connectionString))
65 {
66 string querySql = @"SELECT [Id]
67 ,[UserName]
68 ,[Password]
69 ,[Gender]
70 ,[Birthday]
71 ,[CreateUserId]
72 ,[CreateDate]
73 ,[UpdateUserId]
74 ,[UpdateDate]
75 ,[IsDeleted]
76 FROM [dbo].[User]";
77 return conn.Query<User>(querySql);
78 }
79 }
80
81 /// <summary>
82 /// 根据主键Id获取一个用户
83 /// </summary>
84 /// <param name="id">主键Id</param>
85 /// <param name="connectionString">链接字符串</param>
86 /// <returns></returns>
87 public User RetriveOneEntityById(int id, string connectionString = null)
88 {
89 using (IDbConnection conn = DataBaseConfig.GetSqlConnection(connectionString))
90 {
91 string querySql = @"SELECT [Id]
92 ,[UserName]
93 ,[Password]
94 ,[Gender]
95 ,[Birthday]
96 ,[CreateUserId]
97 ,[CreateDate]
98 ,[UpdateUserId]
99 ,[UpdateDate]
100 ,[IsDeleted]
101 FROM [dbo].[User]
102 WHERE Id = @Id";
103 return conn.QueryFirstOrDefault<User>(querySql, new { Id = id });
104 }
105 }
106
107 /// <summary>
108 /// 修改一个用户
109 /// </summary>
110 /// <param name="entity">要修改的用户</param>
111 /// <param name="connectionString">链接字符串</param>
112 /// <returns></returns>
113 public bool UpdateEntity(User entity, string connectionString = null)
114 {
115 using (IDbConnection conn = DataBaseConfig.GetSqlConnection(connectionString))
116 {
117 string updateSql = @"UPDATE [dbo].[User]
118 SET [UserName] = @UserName
119 ,[Password] = @Password
120 ,[Gender] = @Gender
121 ,[Birthday] = @Birthday
122 ,[UpdateUserId] = @UpdateUserId
123 ,[UpdateDate] = @UpdateDate
124 ,[IsDeleted] = @IsDeleted
125 WHERE Id = @Id";
126 return conn.Execute(updateSql, entity) > 0;
127 }
128 }
129 }
上面的代码所执行的方法Execute,Query,QueryFirstOrDefault其实都是IDbConnection的扩展方法,转到定义你也可以清楚的看到默认buffered缓存是开启的,并且都支持事务提交,同时还都对应各自的async异步方法
public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?));
这样一来,再也不用DataReader去一个一个属性赋值了,也不用SqlParameter一个一个去参数化了,Dapper全部帮你做了,你只需要关注你的业务SQL语句以及上下文的对象即可,是不是很清爽!
c)、接下来就是完成对上一部分仓储数据的调用。一方面是IBusiness的服务接口定义,另一方面则是Business的简单实现,因为暂时只是涉及到一个表的增查改删,所以具体的代码就不上了
d)、至于依赖注入模块,我直接使用的是Microsoft.Extensions.DependencyInjection,所有的服务由ServiceCollection服务容器进行管理,我们只需要将接口和它的实现类进行注册就行了
1 /// <summary>
2 /// 注入业务逻辑层
3 /// </summary>
4 public class BusinessInjection
5 {
6 public static void ConfigureBusiness(IServiceCollection services)
7 {
8 services.AddSingleton<IUserBusiness, UserBusiness>();
9 }
10 }
1 /// <summary>
2 /// 注入仓储层
3 /// </summary>
4 public class RepositoryInjection
5 {
6 public static void ConfigureRepository(IServiceCollection services)
7 {
8 services.AddSingleton<IUserRepository, UserRepository>();
9 }
10 }
三、引入SwaggerUI
简介:SwaggerUI是一款针对WebApi的可视化工具,同样我也称它是一款全自动的接口描述文档,并且可以很方便的帮助你测试你的接口,接下来我们一步一步的来把它添加进去。
1、向ASP.NET Core WebApi项目中添加Swashbuckle组件,打开包管理控制台,输入:
Install-Package Swashbuckle -Pre
记得加上后边的-Pre,表示安装最新版本,否则的话会默认下载稳定版本5.5.3(不支持Core)
当然了,你也可以包管理器进行安装,记得勾选“包括预发行版”,然后选择6.0.0-beta902进行安装

2、打开Startup文件,添加Swagger中间件并将他们注入到应用程序的管道中,同时也将我们自定义的服务加进去
1 /// <summary>
2 /// This method gets called by the runtime. Use this method to add services to the container.
3 /// </summary>
4 /// <param name="services"></param>
5 public void ConfigureServices(IServiceCollection services)
6 {
7 RepositoryInjection.ConfigureRepository(services);
8 BusinessInjection.ConfigureBusiness(services);
9 services.AddMvc();
10 services.AddSwaggerGen();
11 }
12
13 /// <summary>
14 /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
15 /// </summary>
16 /// <param name="app"></param>
17 /// <param name="env"></param>
18 /// <param name="loggerFactory"></param>
19 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
20 {
21 loggerFactory.AddConsole(Configuration.GetSection("Logging"));
22 loggerFactory.AddDebug();
23
24 app.UseMvc();
25 app.UseSwagger();
26 app.UseSwaggerUi();
27 }
3、打开launchSettings文件,修改launchUrl为“swagger/ui”
1 "profiles": {
2 "IIS Express": {
3 "commandName": "IISExpress",
4 "launchBrowser": true,
5 "launchUrl": "swagger/ui",
6 "environmentVariables": {
7 "ASPNETCORE_ENVIRONMENT": "Development"
8 }
9 },
10 "Light.Api": {
11 "commandName": "Project",
12 "launchBrowser": true,
13 "launchUrl": "swagger/ui",
14 "environmentVariables": {
15 "ASPNETCORE_ENVIRONMENT": "Development"
16 },
17 "applicationUrl": "http://localhost:62116"
18 }
19 }
4、添加一个UserController,针对每一个服务增加一个REST风格的API接口。注意使用的HttpMethod方法。HttpGet表示获取对象,HttpPost表示创建对象,HttpPut表示修改对象,HttpDelete表示删除对象
1 /// <summary>
2 /// 用户控制器
3 /// </summary>
4 [Route("api/[controller]")]
5 public class UserController : Controller
6 {
7 private readonly IUserBusiness iUserBusiness;
8 /// <summary>
9 /// 构造函数注入服务
10 /// </summary>
11 /// <param name="userBusiness"></param>
12 public UserController(IUserBusiness userBusiness)
13 {
14 iUserBusiness = userBusiness;
15 }
16
17 /// <summary>
18 /// 获取所有用户
19 /// </summary>
20 /// <returns></returns>
21 [HttpGet]
22 //[Route("AllUser")]
23 public IEnumerable<User> GetAllUser()
24 {
25 return iUserBusiness.RetriveAllEntity();
26 }
27
28 /// <summary>
29 /// 根据主键Id获取一个用户
30 /// </summary>
31 /// <param name="id">主键Id</param>
32 /// <returns></returns>
33 [HttpGet("{id}")]
34 public User GetOneUser(int id)
35 {
36 return iUserBusiness.RetriveOneEntityById(id);
37 }
38
39 /// <summary>
40 /// 新增用户
41 /// </summary>
42 /// <param name="user">用户实体</param>
43 /// <returns></returns>
44 [HttpPost]
45 public bool CreateUser([FromBody]User user)
46 {
47 return iUserBusiness.CreateEntity(user);
48 }
49
50 /// <summary>
51 /// 修改用户
52 /// </summary>
53 /// <param name="id">主键Id</param>
54 /// <param name="user">用户实体</param>
55 /// <returns></returns>
56 [HttpPut("{id}")]
57 public bool UpdateUser(int id, [FromBody]User user)
58 {
59 user.Id = id;
60 return iUserBusiness.UpdateEntity(user);
61 }
62
63 /// <summary>
64 /// 根据主键Id删除一个用户
65 /// </summary>
66 /// <param name="id">主键Id</param>
67 /// <returns></returns>
68 [HttpDelete("{id}")]
69 public bool DeleteUser(int id)
70 {
71 return iUserBusiness.DeleteEntityById(id);
72 }
73 }
View Code