1. 程式人生 > >ASP.NET Core:使用Dapper和SwaggerUI來豐富你的系統框架

ASP.NET Core:使用Dapper和SwaggerUI來豐富你的系統框架

fig targe api 依賴 dev 多表 efault 方便 div

一、概述

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類庫

更多創建類型請鍵入如下命令進行查看

dotnet new -all

技術分享

紅框內自上而下依次表示:

  • 控制臺應用程序
  • 類庫
  • 微軟自帶的單元測試項目
  • 引入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
技術分享

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     }
技術分享

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     }
技術分享

4、主角進場。通過Nuget引入Dapper到Repository中,目前的版本為1.50.2

Install-Package Dapper
  • Dapper是目前一款簡潔、高效並且開源的ORM(實體對象關系映射)框架之一。
    傳送門:https://github.com/StackExchange/Dapper
  • 它不僅支持Sql Server,還適用於MySql,SqlLite,Oracle,PostgreSql等
  • 默認使用參數化進行查詢或者新增
  • 支持存儲過程
  • 支持級聯映射和多表映射
  • 默認緩沖你所執行的SQL

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     }
技術分享

5、大功告成,Ctrl+F5運行你的程序,並試著執行添加,修改和查詢的Api,體驗Swagger帶給你的方便之處。

技術分享

寫在最後:這篇文章只是介紹了它們倆最簡單最基本的用法,如果其中說法有誤的,還望各位前輩多多指點,更多的內容還需要後續的繼續積累和學習,加油!

ASP.NET Core:使用Dapper和SwaggerUI來豐富你的系統框架