SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务
一、引言
最近SmartSql被正式引入到了NCC,借着这个契机写一个使用教程系列
二、SmartSql简介[摘自官方文档]
1. SmartSql是什么?
SmartSql = MyBatis + Cache(Memory | Redis) + R/W Splitting +Dynamic Repository + Diagnostics ......
2. SmartSql的特性
简洁、高效、高性能、扩展性、监控、渐进式开发!
3. 她是如何工作的?
SmartSql 借鉴了 MyBatis 的思想,使用 XML 来管理 SQL ,并且提供了若干个筛选器标签来消除代码层面的各种 if/else 的判断分支。
SmartSql将管理你的 SQL ,并且通过筛选标签来维护本来你在代码层面的各种条件判断,使你的代码更加优美。
4. 为什么选择SmartSql?
DotNet 体系下大都是 Linq 系的 ORM,Linq 很好,消除了开发人员对 SQL 的依赖。 但却忽视了一点,SQL 本身并不复杂,而且在复杂查询场景当中开发人员很难通过编写Linq来生成良好性能的SQL,相信使用过EF的同学一定有这样的体验:“我想好了Sql怎么写,然后再来写Linq,完了可能还要再查看一下Linq输出的Sql是什么样的“。这是非常糟糕的体验。要想对Sql做绝对的优化,那么开发者必须对Sql有绝对的控制权。另外Sql本身很简单,为何要增加一层翻译器呢?
三、开始SmartSql之旅
知道了SmartSql是什么,那接下来我们开始创建一个项目从0开始使用SmartSql写一个简单的CURD接口服务。
先上一个项目结构,然后我们一一分析他们的作用
1. 创建DB
这里我用的DB是MSSql,直接贴脚本了。
Create DatabaseSmartSqlSampleGO
UseSmartSqlSampleGO
Create TableT_Article (Idbigint not null primary key identity(1,1),Titlenvarchar(255) not null,Contentnvarchar(max) null,Authornvarchar(255) null,Statusint not null,CreateTimedatetime not null default getdate(),ModifiedTimedatetime 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.Ji5 // Date 2019-05-106 // Github : https://github.com/noahjzc/SmartSqlSample7 //*******************************-->
8 <SmartSqlMapConfigxmlns="http://SmartSql.net/schemas/SmartSqlMapConfig.xsd">
9 <!--允许使用缓存(以后章节细讲)-->
10 <SettingsIsCacheEnabled="true" />
11 <!--属性、特性配置节点,这里只配置一个连接字符串-->
12 <Properties>
13 <PropertyName="ConnectionString"Value="Data Source=localhost;database=SmartSqlSample;uid=sa;pwd=123456" />
14 <PropertyName="ReadOneConnectionString"Value="Data Source=123.123.123.123;database=SmartSqlSample;uid=sa;pwd=123456" />
15 </Properties>
16 <!--数据库配置 Start-->
17 <Database>
18 <DbProviderName="SqlServer" />
19 <WriteName="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 <SmartSqlMapPath="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 <SmartSqlMapScope="Article"xmlns="http://SmartSql.net/schemas/SmartSqlMap.xsd">
2 ...3 </SmartSqlMap>
这里的关键在于Scope,这个属性是用于定位Map的。
2.3.2 CUD配置
<!--新增-->
<StatementId="Insert">INSERT INTO T_Article(Title,Content,Author,Status,CreateTime,ModifiedTime)VALUES(@Title,@Content,@Author,@Status,@CreateTime,GetDate());SELECT Scope_Identity();</Statement>
<!--删除-->
<StatementId="Delete">DELETE T_Article WHERE Id = @Id</Statement>
<!--更新-->
<StatementId="Update">UPDATE T_Article<Set>ModifiedTime = GetDate()<IsPropertyPrepend=","Property="Title">Title = @Title</IsProperty><IsPropertyPrepend=","Property="Content">Content = @Content</IsProperty><IsPropertyPrepend=","Property="Author">Author = @Author</IsProperty><IsPropertyPrepend=","Property="Status">Status = @Status</IsProperty><IsPropertyPrepend=","Property="CreateTime">CreateTime = @CreateTime</IsProperty></Set>Where id=@Id</Statement>
CUD配置
2.3.3 通用查询节点
<StatementId="QueryParams"><Where><IsGreaterEqualPrepend="And"Property="Id"CompareValue="0">T.Id = @Id</IsGreaterEqual><IsNotEmptyPrepend="And"Property="Title">T.Title Like '%'+@Title+'%'</IsNotEmpty><IsNotEmptyPrepend="And"Property="Ids">T.Id IN @Ids</IsNotEmpty></Where>
</Statement>
通用查询节点
这个Statement节点其实和别的节点没什么区别。SmartSql允许Statement的嵌套。使用规则如下面这段配置
<StatementId="Query">SELECT T.* FROM T_Article T<IncludeRefId="QueryParams" /><SwitchPrepend="Order By"Property="OrderBy"><Default>T.id Desc</Default></Switch><IsNotEmptyPrepend="Limit"Property="Taken">@Taken</IsNotEmpty>
</Statement>
Query
在这段Query配置中。我们使用了Include标签来引入上面定义好的Id为QueryParams的Statement,这样就做到了查询配置的通用性。例如我还可以将QueryParams配置到分页和查询结果数的配置中。如下:
<!--获取分页数据-->
<StatementId="QueryByPage">SELECT T.* FROM T_Article As T<IncludeRefId="QueryParams" /><SwitchPrepend="Order By"Property="OrderBy"><Default>T.Id Desc</Default></Switch>Offset ((@PageIndex-1)*@PageSize) Rows Fetch Next @PageSize Rows Only;</Statement><!--获取记录数-->
<StatementId="GetRecord">SELECT Count(1) FROM T_Article T<IncludeRefId="QueryParams" />
</Statement>
分页及结果数查询
2.4 Startup
注入SmartSql
//register smartsql
services.AddSmartSql(builder =>{builder.UseAlias("SmartSqlSampleChapterOne"); //定义实例别名,在多库场景下适用。//.UseXmlConfig(ResourceType.File,"MyConfig.xml");
});
在2.2中我们把基础配置文件命名为SmartSqlMapConfig。这个是默认文件名,我们也可以像上面的注释代码一样。自定义配置文件的名称。
3. 让配置工作起来
其实到了这一步一切都顺其自然了。我感觉没有什么可以多讲了。直接上代码了!
1 usingMicrosoft.Extensions.DependencyInjection;2 usingSmartSql;3 usingSmartSqlSampleChapterOne.Entity;4 usingSystem;5 usingSystem.Collections.Generic;6
7 namespaceSmartSqlSampleChapterOne.DataAccess8 {9 /// <summary>
10 ///
11 /// </summary>
12 public classArticleDataAccess13 {14 private readonlyISqlMapper _sqlMapper;15
16 /// <summary>
17 ///
18 /// </summary>
19 /// <param name="sp"></param>
20 publicArticleDataAccess(IServiceProvider sp)21 {22 _sqlMapper = sp.GetSmartSql("SmartSqlSampleChapterOne").SqlMapper;23 }24
25 /// <summary>
26 ///Insert27 /// </summary>
28 /// <param name="article"></param>
29 /// <returns></returns>
30 public longInsert(T_Article article)31 {32 return _sqlMapper.ExecuteScalar<long>(newRequestContext33 {34 Scope = "Article",35 SqlId = "Insert",36 Request =article37 });38 }39
40 /// <summary>
41 ///Update42 /// </summary>
43 /// <param name="article"></param>
44 /// <returns></returns>
45 public intUpdate(T_Article article)46 {47 return _sqlMapper.Execute(newRequestContext48 {49 Scope = "Article",50 SqlId = "Update",51 Request =article52 });53 }54
55 /// <summary>
56 ///DyUpdate57 /// </summary>
58 /// <param name="updateObj"></param>
59 /// <returns></returns>
60 public int DyUpdate(objectupdateObj)61 {62 return _sqlMapper.Execute(newRequestContext63 {64 Scope = "Article",65 SqlId = "Update",66 Request =updateObj67 });68 }69
70 /// <summary>
71 ///Delete72 /// </summary>
73 /// <param name="id"></param>
74 /// <returns></returns>
75 public int Delete(longid)76 {77 return _sqlMapper.Execute(newRequestContext78 {79 Scope = "Article",80 SqlId = "Delete",81 Request = new { Id =id }82 });83 }84
85 /// <summary>
86 ///GetById87 /// </summary>
88 /// <param name="id"></param>
89 /// <returns></returns>
90 public T_Article GetById(longid)91 {92 return _sqlMapper.QuerySingle<T_Article>(newRequestContext93 {94 Scope = "Article",95 SqlId = "GetEntity",96 Request = new { Id =id }97 });98 }99
100 /// <summary>
101 ///Query102 /// </summary>
103 /// <param name="queryParams"></param>
104 /// <returns></returns>
105 public IEnumerable<T_Article> Query(objectqueryParams)106 {107 return _sqlMapper.Query<T_Article>(newRequestContext108 {109 Scope = "Article",110 SqlId = "Query",111 Request =queryParams112 });113 }114
115 /// <summary>
116 ///GetRecord117 /// </summary>
118 /// <param name="queryParams"></param>
119 /// <returns></returns>
120 public int GetRecord(objectqueryParams)121 {122 return _sqlMapper.ExecuteScalar<int>(newRequestContext123 {124 Scope = "Article",125 SqlId = "GetRecord",126 Request =queryParams127 });128 }129
130 /// <summary>
131 ///IsExist132 /// </summary>
133 /// <param name="queryParams"></param>
134 /// <returns></returns>
135 public bool IsExist(objectqueryParams)136 {137 return _sqlMapper.QuerySingle<bool>(newRequestContext138 {139 Scope = "Article",140 SqlId = "IsExist",141 Request =queryParams142 });143 }144 }145 }
ArticleDataAccess
4. 最后一步
4.1 ArticleController
有了DataAccess我们可以轻松的操作数据库了。最后一步我们建立一个Controller,对外暴露一些接口吧。
usingMicrosoft.AspNetCore.Mvc;usingSmartSqlSampleChapterOne.DataAccess;usingSmartSqlSampleChapterOne.Entity;usingSystem.Collections.Generic;namespaceSmartSqlSampleChapterOne.Controllers
{/// <summary>/// /// </summary>[Route("[controller]/[action]")]public classArticleController : Controller{private readonlyArticleDataAccess _articleDataAccess;/// <summary>///constructor/// </summary>/// <param name="articleDataAccess"></param>publicArticleController(ArticleDataAccess articleDataAccess){_articleDataAccess=articleDataAccess;}/// <summary>/// /// </summary>/// <param name="article"></param>/// <returns></returns>
[HttpPost]publicT_Article Add([FromBody] T_Article article){article.Id=_articleDataAccess.Insert(article);returnarticle;}/// <summary>/// /// </summary>/// <param name="id"></param>/// <returns></returns>
[HttpGet]public T_Article Get([FromQuery] longid){return_articleDataAccess.GetById(id);}/// <summary>/// /// </summary>/// <param name="article"></param>/// <returns></returns>
[HttpPost]public boolUpdate([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] intstatus){return _articleDataAccess.DyUpdate(new{Id=id,Status=status})> 0;}/// <summary>/// /// </summary>/// <param name="id"></param>/// <returns></returns>
[HttpGet]public bool IsExist([FromQuery] longid){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 usingMicrosoft.AspNetCore.Builder;2 usingMicrosoft.AspNetCore.Hosting;3 usingMicrosoft.Extensions.Configuration;4 usingMicrosoft.Extensions.DependencyInjection;5 usingMicrosoft.Extensions.Logging;6 usingSwashbuckle.AspNetCore.Swagger;7 usingSystem;8 usingSystem.IO;9 usingSmartSql.ConfigBuilder;10 usingSmartSqlSampleChapterOne.DataAccess;11
12 namespaceSmartSqlSampleChapterOne13 {14 public classStartup15 {16 publicStartup(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, visithttps://go.microsoft.com/fwlink/?LinkID=398940
24 public voidConfigureServices(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", newInfo48 {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 voidConfigure(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
转载于:https://www.cnblogs.com/noahji/p/10846215.html
SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务相关推荐
- stm32单片机c语言入门,STM32入门教程1,初学者入门,从零开始,使用keil建立一个简单的ST...
本文讲述的是如何从零开始,使用keil建立一个简单的STM32的工程,并闪烁LED灯,给小白看. 第零步,当然首先你得有一个STM32的板子,其IO口上接了一个LED... 第一步,建立一个文件夹0. ...
- 机器人坐标系建立_如何在30分钟内建立一个简单的搜索机器人
机器人坐标系建立 by Quinn Langille 奎因·兰吉尔(Quinn Langille) 如何在30分钟内建立一个简单的搜索机器人 (How to Build A Simple Search ...
- python追踪屏幕的移动目标_利用树莓派和Python建立一个简单、便宜的移动目标探测器...
今天我们将讨论如何建立一个简单.便宜的移动目标探测器. 这项研究的目的是确定在一个便宜的移动设备上的对象检测模型是否可以用于现实世界的任务. 作为一个移动平台,我们使用的是树莓派3B.树莓派是一款售价 ...
- 利用OpenAI Gym建立一个简单的自动驾驶模拟器
(长按识别上方二维码,报名第29届IEEE IV大会 ) 如何建立一个简单的自动驾驶汽车模拟器?本文作者蒙特利尔大学专注于编译器设计 Maxime Chevalier 博士,在OpenAI Gym环境 ...
- bat 删除文件_利用电脑文本文档建立一个简单方便的删除文件的小程序
删除文不需要的文件或者资料,是日常工作中必定会遇到了. 各种的杀毒软件或者防护软件都具备删除文件的功能,例如360.腾讯电脑管家.这些操作起来其实也不是太麻烦! 不过呢!今天来和大家分享一个更简单的方 ...
- tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数
tensorflow学习笔记二--建立一个简单的神经网络 2016-09-23 16:04 2973人阅读 评论(2) 收藏 举报 分类: tensorflow(4) 目录(?)[+] 本笔记目的 ...
- Hibernate学习——建立一个简单的Hibernate项目
最近老师让做个web小应用,大三的时候学习过一点J2EE的东西,也做过一些web相关的XXX管理系统,都是用servlet,jsp这些完成的,虽然勉强能够完成任务,但其中各种代码掺杂在一起,不好看而且 ...
- 使用html 语言建立一个简单的网页,如何用记事本建立简单的网页(1).doc
第九章 网页制作 实验一 用记事本建立简单的HTML文件 [实验目的] 学会用HTML语言建立一个简单的网页. [实验内容] 建立一个网页,布局自定,包括自我介绍.图片.自己的电子信箱地址等,要求在标 ...
- 怎么建立一个简单的程序化交易系统?
怎么建立一个简单的程序化交易系统? 交易系统构成就有好几个部分,主要给大家介绍一个简单的交易系统的构成. 简单的交易系统建立的话至少要包括3个部分,即入市信号系统.离市信号系统.资金风险控制系统. 入 ...
最新文章
- 【通俗理解线性代数】 -- 特殊的矩阵
- 机器学习数学基础系列|凸优化——开启新世界的大门(上)
- 你不知道的JavaScript·第一部分
- Windows 7怎么关闭自动播放功能?
- 20个 css3 html5 设计工具
- 自定义的Sort对象
- SAP Spartacus category在breadcrumb里显示不正确的一个问题
- linux awk 日志分析,Linux Awk使用案例总结 nginx日志统计
- sync.Once简介
- 利用iPhone下载其他地区的App
- Windows Server 2008 R2从低版本升级到高版本
- 2019年java全栈工程师学习大全
- 射灯安装方法图解_射灯如何安装—射灯的安装方法介绍
- “80后”全国模范检察官白静:传递青年干警正能量
- RK3588 烧写固件
- XCP实战系列介绍16-XCP标定过程指令解析
- MVC设计模式及Sprint MVC设计模式
- 通用寄存器介绍和段寄存器的介绍
- 杭电 OJ 1029
- 软阈值(Soft Thresholding) 函数解读