SmartSql使用教程(1)——初探,創建一個簡單的CURD接口服務

1、引言

最近SmartSql被正式引入到了NCC,藉着這個契機寫一個使用教程系列git

 

2、SmartSql簡介[摘自官方文檔]

1. SmartSql是什麼?

SmartSql = MyBatis + Cache(Memory | Redis) + R/W Splitting +Dynamic Repository + Diagnostics ......github

2. SmartSql的特性

簡潔、高效、高性能、擴展性、監控、漸進式開發!sql

3. 她是如何工做的?

  SmartSql 借鑑了 MyBatis 的思想,使用 XML 來管理 SQL ,而且提供了若干個篩選器標籤來消除代碼層面的各類 if/else 的判斷分支。數據庫

  SmartSql將管理你的 SQL ,而且經過篩選標籤來維護原本你在代碼層面的各類條件判斷,使你的代碼更加優美。json

4. 爲何選擇SmartSql?

  DotNet 體系下大都是 Linq 系的 ORM,Linq 很好,消除了開發人員對 SQL 的依賴。 但卻忽視了一點,SQL 自己並不複雜,並且在複雜查詢場景當中開發人員很難經過編寫Linq來生成良好性能的SQL,相信使用過EF的同窗必定有這樣的體驗:「我想好了Sql怎麼寫,而後再來寫Linq,完了可能還要再查看一下Linq輸出的Sql是什麼樣的「。這是很是糟糕的體驗。要想對Sql作絕對的優化,那麼開發者必須對Sql有絕對的控制權。另外Sql自己很簡單,爲什麼要增長一層翻譯器呢?緩存

 

3、開始SmartSql之旅

  知道了SmartSql是什麼,那接下來咱們開始建立一個項目從0開始使用SmartSql寫一個簡單的CURD接口服務。app

  先上一個項目結構,而後咱們一一分析他們的做用ide

 

1. 建立DB

  這裏我用的DB是MSSql,直接貼腳本了。性能

Create Database SmartSqlSample GO
Use SmartSqlSample GO
Create Table T_Article ( Id bigint not null primary key identity(1,1), Title nvarchar(255) not null, Content nvarchar(max) null, Author nvarchar(255) null, Status int not null, CreateTime datetime not null default getdate(), ModifiedTime datetime not null default getdate() )
Init腳本

2. SmartSql 基礎配置

2.1 添加Nuget依賴

  SmartSql的庫能夠直接在Nuget上找到,但由於.NetCoreMVC的項目如今自帶了DI依賴注入的關係,咱們只須要直接引用SmartSql.DI.Extension就能夠了。測試

  項目的依賴性包括了

  1. AspNetCore基礎庫

  2. SmartSql.DI.Extension(咱們的主角)

  3. Swashbuckle.AspNetCore(方便咱們接口測試)

 

2.2 添加SmartSql配置文件

  SmartSql是一個基於Xml配置的ORM。這點和Mybatis沒有什麼不一樣。若是你熟悉Mybatis,相信你很快就能適應SmartSql。若是你之前沒接觸過相似的ORM。那請跟着這個教程,一步一步瞭解SmartSql的強大。

  SmartSqlMapConfig.xml,SmartSql的起點。

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <!--
 3 //*******************************  4 // Create By Noah.Ji  5 // Date 2019-05-10  6 // Github : https://github.com/noahjzc/SmartSqlSample  7 //*******************************-->
 8 <SmartSqlMapConfig xmlns="http://SmartSql.net/schemas/SmartSqlMapConfig.xsd">
 9   <!-- 容許使用緩存(之後章節細講) -->
10   <Settings IsCacheEnabled="true" />
11   <!-- 屬性、特性配置節點,這裏只配置一個鏈接字符串 -->
12   <Properties>
13     <Property Name="ConnectionString" Value="Data Source=localhost;database=SmartSqlSample;uid=sa;pwd=123456" />
14     <Property Name="ReadOneConnectionString" Value="Data Source=123.123.123.123;database=SmartSqlSample;uid=sa;pwd=123456" />
15   </Properties>
16   <!-- 數據庫配置 Start -->
17   <Database>
18     <DbProvider Name="SqlServer" />
19     <Write Name="Sample-Write" ConnectionString="${ConnectionString}" />
20     <!-- 多讀節點配置 -->
21     <!--
22  <Read Name="Sample-Node-1" ConnectionString="${ReadOneConnectionString}" Weight="60"/> 23  <Read Name="Sample-Node-2" ConnectionString="Data Source=456.456.456.456;database=SmartSqlSample;uid=sa;pwd=123456" Weight="40"/> 24     -->
25   </Database>
26   <!-- 數據庫配置 End -->
27   <!-- 數據Map配置 Start -->
28   <SmartSqlMaps>
29     <!-- 文件夾 -->
30     <SmartSqlMap Path="Maps" Type="Directory"></SmartSqlMap>
31 
32     <!-- 文件夾及子集(遞歸獲取文件夾下全部Map文件) -->
33     <!--<SmartSqlMap Path="Maps" Type="DirectoryWithAllSub"></SmartSqlMap>-->
34 
35     <!-- 單個文件 -->
36     <!--<SmartSqlMap Path="Maps/T_Article.xml" Type="File"></SmartSqlMap>-->
37 
38     <!-- 嵌入式資源 -->
39     <!--<SmartSqlMap Path="SmartSqlSampleChapterOne.Maps.T_Article.xml, SmartSqlSampleChapterOne" Type="Embedded"></SmartSqlMap>-->
40 
41     <!-- http資源 -->
42     <!--<SmartSqlMap Type="Uri" Path="https://smartsql.net/Maps/T_Article.xml" />-->
43   </SmartSqlMaps>
44   <!-- 數據Map配置 End -->
45 </SmartSqlMapConfig>

2.3 表Map配置

2.3.1 Root節點

1 <SmartSqlMap Scope="Article" xmlns="http://SmartSql.net/schemas/SmartSqlMap.xsd">
2 ... 3 </SmartSqlMap>

這裏的關鍵在於Scope,這個屬性是用於定位Map的。

2.3.2 CUD配置

<!--新增-->
<Statement Id="Insert"> INSERT INTO T_Article (Title ,Content ,Author ,Status ,CreateTime ,ModifiedTime ) VALUES (@Title ,@Content ,@Author ,@Status ,@CreateTime ,GetDate() ); SELECT Scope_Identity(); </Statement>
<!--刪除-->
<Statement Id="Delete"> DELETE T_Article WHERE Id = @Id </Statement>
<!--更新-->
<Statement Id="Update"> UPDATE T_Article <Set> ModifiedTime = GetDate() <IsProperty Prepend="," Property="Title"> Title = @Title </IsProperty>
    <IsProperty Prepend="," Property="Content"> Content = @Content </IsProperty>
    <IsProperty Prepend="," Property="Author"> Author = @Author </IsProperty>
    <IsProperty Prepend="," Property="Status"> Status = @Status </IsProperty>
    <IsProperty Prepend="," Property="CreateTime"> CreateTime = @CreateTime </IsProperty>
  </Set> Where id=@Id </Statement>
CUD配置

2.3.3 通用查詢節點

<Statement Id="QueryParams">
  <Where>
    <IsGreaterEqual Prepend="And" Property="Id" CompareValue="0"> T.Id = @Id </IsGreaterEqual>
    <IsNotEmpty Prepend="And" Property="Title"> T.Title Like '%'+@Title+'%' </IsNotEmpty>
    <IsNotEmpty Prepend="And" Property="Ids"> T.Id IN @Ids </IsNotEmpty>
  </Where>
</Statement>
通用查詢節點

這個Statement節點其實和別的節點沒什麼區別。SmartSql容許Statement的嵌套。使用規則以下面這段配置

<Statement Id="Query"> SELECT T.* FROM T_Article T <Include RefId="QueryParams" />
  <Switch Prepend="Order By" Property="OrderBy">
    <Default> T.id Desc </Default>
  </Switch>
  <IsNotEmpty Prepend="Limit" Property="Taken">@Taken</IsNotEmpty>
</Statement>
Query

在這段Query配置中。咱們使用了Include標籤來引入上面定義好的Id爲QueryParams的Statement,這樣就作到了查詢配置的通用性。例如我還能夠將QueryParams配置到分頁和查詢結果數的配置中。以下:

<!--獲取分頁數據-->
<Statement Id="QueryByPage"> SELECT T.* FROM T_Article As T <Include RefId="QueryParams" />
  <Switch Prepend="Order By" Property="OrderBy">
    <Default> T.Id Desc </Default>
  </Switch> Offset ((@PageIndex-1)*@PageSize) Rows Fetch Next @PageSize Rows Only; </Statement>

<!--獲取記錄數-->
<Statement Id="GetRecord"> SELECT Count(1) FROM T_Article T <Include RefId="QueryParams" />
</Statement>
分頁及結果數查詢

2.4 Startup

注入SmartSql

// register smartsql
services.AddSmartSql(builder => { builder.UseAlias("SmartSqlSampleChapterOne");       // 定義實例別名,在多庫場景下適用。 //.UseXmlConfig(ResourceType.File,"MyConfig.xml");
});

在2.2中咱們把基礎配置文件命名爲SmartSqlMapConfig。這個是默認文件名,咱們也能夠像上面的註釋代碼同樣。自定義配置文件的名稱。

 

3. 讓配置工做起來

其實到了這一步一切都順其天然了。我感受沒有什麼能夠多講了。直接上代碼了!

 1 using Microsoft.Extensions.DependencyInjection;  2 using SmartSql;  3 using SmartSqlSampleChapterOne.Entity;  4 using System;  5 using System.Collections.Generic;  6 
 7 namespace SmartSqlSampleChapterOne.DataAccess  8 {  9     /// <summary>
 10     /// 
 11     /// </summary>
 12     public class ArticleDataAccess  13  {  14         private readonly ISqlMapper _sqlMapper;  15 
 16         /// <summary>
 17         /// 
 18         /// </summary>
 19         /// <param name="sp"></param>
 20         public ArticleDataAccess(IServiceProvider sp)  21  {  22             _sqlMapper = sp.GetSmartSql("SmartSqlSampleChapterOne").SqlMapper;  23  }  24 
 25         /// <summary>
 26         /// Insert  27         /// </summary>
 28         /// <param name="article"></param>
 29         /// <returns></returns>
 30         public long Insert(T_Article article)  31  {  32             return _sqlMapper.ExecuteScalar<long>(new RequestContext  33  {  34                 Scope = "Article",  35                 SqlId = "Insert",  36                 Request = article  37  });  38  }  39 
 40         /// <summary>
 41         /// Update  42         /// </summary>
 43         /// <param name="article"></param>
 44         /// <returns></returns>
 45         public int Update(T_Article article)  46  {  47             return _sqlMapper.Execute(new RequestContext  48  {  49                 Scope = "Article",  50                 SqlId = "Update",  51                 Request = article  52  });  53  }  54 
 55         /// <summary>
 56         /// DyUpdate  57         /// </summary>
 58         /// <param name="updateObj"></param>
 59         /// <returns></returns>
 60         public int DyUpdate(object updateObj)  61  {  62             return _sqlMapper.Execute(new RequestContext  63  {  64                 Scope = "Article",  65                 SqlId = "Update",  66                 Request = updateObj  67  });  68  }  69 
 70         /// <summary>
 71         /// Delete  72         /// </summary>
 73         /// <param name="id"></param>
 74         /// <returns></returns>
 75         public int Delete(long id)  76  {  77             return _sqlMapper.Execute(new RequestContext  78  {  79                 Scope = "Article",  80                 SqlId = "Delete",  81                 Request = new { Id = id }  82  });  83  }  84 
 85         /// <summary>
 86         /// GetById  87         /// </summary>
 88         /// <param name="id"></param>
 89         /// <returns></returns>
 90         public T_Article GetById(long id)  91  {  92             return _sqlMapper.QuerySingle<T_Article>(new RequestContext  93  {  94                 Scope = "Article",  95                 SqlId = "GetEntity",  96                 Request = new { Id = id }  97  });  98  }  99 
100         /// <summary>
101         /// Query 102         /// </summary>
103         /// <param name="queryParams"></param>
104         /// <returns></returns>
105         public IEnumerable<T_Article> Query(object queryParams) 106  { 107             return _sqlMapper.Query<T_Article>(new RequestContext 108  { 109                 Scope = "Article", 110                 SqlId = "Query", 111                 Request = queryParams 112  }); 113  } 114 
115         /// <summary>
116         /// GetRecord 117         /// </summary>
118         /// <param name="queryParams"></param>
119         /// <returns></returns>
120         public int GetRecord(object queryParams) 121  { 122             return _sqlMapper.ExecuteScalar<int>(new RequestContext 123  { 124                 Scope = "Article", 125                 SqlId = "GetRecord", 126                 Request = queryParams 127  }); 128  } 129 
130         /// <summary>
131         /// IsExist 132         /// </summary>
133         /// <param name="queryParams"></param>
134         /// <returns></returns>
135         public bool IsExist(object queryParams) 136  { 137             return _sqlMapper.QuerySingle<bool>(new RequestContext 138  { 139                 Scope = "Article", 140                 SqlId = "IsExist", 141                 Request = queryParams 142  }); 143  } 144  } 145 }
ArticleDataAccess

 

4. 最後一步

4.1 ArticleController

有了DataAccess咱們能夠輕鬆的操做數據庫了。最後一步咱們創建一個Controller,對外暴露一些接口吧。

using Microsoft.AspNetCore.Mvc; using SmartSqlSampleChapterOne.DataAccess; using SmartSqlSampleChapterOne.Entity; using System.Collections.Generic; namespace SmartSqlSampleChapterOne.Controllers { /// <summary>
    /// 
    /// </summary>
    [Route("[controller]/[action]")] public class ArticleController : Controller { private readonly ArticleDataAccess _articleDataAccess; /// <summary>
        /// constructor /// </summary>
        /// <param name="articleDataAccess"></param>
        public ArticleController(ArticleDataAccess articleDataAccess) { _articleDataAccess = articleDataAccess; } /// <summary>
        /// 
        /// </summary>
        /// <param name="article"></param>
        /// <returns></returns>
 [HttpPost] public T_Article Add([FromBody] T_Article article) { article.Id = _articleDataAccess.Insert(article); return article; } /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
 [HttpGet] public T_Article Get([FromQuery] long id) { return _articleDataAccess.GetById(id); } /// <summary>
        /// 
        /// </summary>
        /// <param name="article"></param>
        /// <returns></returns>
 [HttpPost] public bool Update([FromBody] T_Article article) { return _articleDataAccess.Update(article) > 0; } /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
 [HttpPost] public bool UpdateStatus([FromQuery] long id, [FromQuery] int status) { return _articleDataAccess.DyUpdate(new { Id = id, Status = status }) > 0; } /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
 [HttpGet] public bool IsExist([FromQuery] long id) { return _articleDataAccess.IsExist(new { Id = id }); } /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
 [HttpGet] public IEnumerable<T_Article> Query([FromQuery] string key = "") { return _articleDataAccess.Query(new { Title = key }); } } }
ArticleController

4.2 Startup

前面咱們已經把SmartSql注入到了DI。如今咱們再完善一下它,把Mvc和Swagger也注入進去。

 1 using Microsoft.AspNetCore.Builder;  2 using Microsoft.AspNetCore.Hosting;  3 using Microsoft.Extensions.Configuration;  4 using Microsoft.Extensions.DependencyInjection;  5 using Microsoft.Extensions.Logging;  6 using Swashbuckle.AspNetCore.Swagger;  7 using System;  8 using System.IO;  9 using SmartSql.ConfigBuilder; 10 using SmartSqlSampleChapterOne.DataAccess; 11 
12 namespace SmartSqlSampleChapterOne 13 { 14     public class Startup 15  { 16         public Startup(IConfiguration configuration) 17  { 18             Configuration = configuration; 19  } 20 
21         public IConfiguration Configuration { get; } 22         // This method gets called by the runtime. Use this method to add services to the container. 23         // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
24         public void ConfigureServices(IServiceCollection services) 25  { 26  services.AddMvc(); 27 
28             services.AddLogging(logging =>
29  { 30  logging.SetMinimumLevel(LogLevel.Trace); 31  logging.AddConsole(); 32  }); 33 
34             // register smartsql
35             services.AddSmartSql(builder =>
36  { 37                 builder.UseAlias("SmartSqlSampleChapterOne");       // 定義實例別名,在多庫場景下適用。 38                 //.UseXmlConfig(ResourceType.File,"MyConfig.xml");
39  }); 40 
41             // register data access
42             services.AddSingleton<ArticleDataAccess>(); 43 
44             // register swagger
45             services.AddSwaggerGen(c =>
46  { 47                 c.SwaggerDoc("SmartSqlSampleChapterOne", new Info 48  { 49                     Title = "SmartSqlSample.ChapterOne", 50                     Version = "v1", 51                     Description = "SmartSqlSample.ChapterOne"
52  }); 53                 var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SmartSqlSampleChapterOne.xml"); 54                 if (File.Exists(filePath)) c.IncludeXmlComments(filePath); 55  }); 56 
57  } 58 
59         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
60         public void Configure(IApplicationBuilder app, IHostingEnvironment env) 61  { 62             if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); 63  app.UseMvc(); 64 
65             app.UseSwagger(c => { }); 66             app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/SmartSqlSampleChapterOne/swagger.json", "SmartSqlSampleChapterOne"); }); 67  } 68  } 69 }
Startup

好了!至此項目的大部分元素都作了一個簡單介紹。咱們來看看最終的運行結果吧。

5. 接口演示

接口預覽

添加接口

獲取接口

查詢接口

 

6. 結語

本篇文章簡單介紹了一下如何使用SmartSql從無到有,完成一個單表的CURD接口實現。但其實SmartSql是一個很是強大的ORM,它還有許多特性沒有展開。再接下來的系列文章中。我會一一爲你們介紹。

示例代碼連接在這裏

 

下期預告:使用動態代理實現CURD

相關文章
相關標籤/搜索