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 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的起点。
<?xml version="1.0" encoding="utf-8" ?>
<!--
//*******************************
// Create By Noah.Ji
// Date 2019-05-10
// Github : https://github.com/noahjzc/SmartSqlSample
//*******************************-->
<SmartSqlMapConfig xmlns="http://SmartSql.net/schemas/SmartSqlMapConfig.xsd">
<!-- 允许使用缓存(以后章节细讲) -->
<Settings IsCacheEnabled="true" />
<!-- 属性、特性配置节点,这里只配置一个连接字符串 -->
<Properties>
<Property Name="ConnectionString" Value="Data Source=localhost;database=SmartSqlSample;uid=sa;pwd=123456" />
<Property Name="ReadOneConnectionString" Value="Data Source=123.123.123.123;database=SmartSqlSample;uid=sa;pwd=123456" />
</Properties>
<!-- 数据库配置 Start -->
<Database>
<DbProvider Name="SqlServer" />
<Write Name="Sample-Write" ConnectionString="${ConnectionString}" />
<!-- 多读节点配置 -->
<!--
<Read Name="Sample-Node-1" ConnectionString="${ReadOneConnectionString}" Weight="60"/>
<Read Name="Sample-Node-2" ConnectionString="Data Source=456.456.456.456;database=SmartSqlSample;uid=sa;pwd=123456" Weight="40"/>
-->
</Database>
<!-- 数据库配置 End -->
<!-- 数据Map配置 Start -->
<SmartSqlMaps>
<!-- 文件夹 -->
<SmartSqlMap Path="Maps" Type="Directory"></SmartSqlMap> <!-- 文件夹及子集(递归获取文件夹下所有Map文件) -->
<!--<SmartSqlMap Path="Maps" Type="DirectoryWithAllSub"></SmartSqlMap>--> <!-- 单个文件 -->
<!--<SmartSqlMap Path="Maps/T_Article.xml" Type="File"></SmartSqlMap>--> <!-- 嵌入式资源 -->
<!--<SmartSqlMap Path="SmartSqlSampleChapterOne.Maps.T_Article.xml, SmartSqlSampleChapterOne" Type="Embedded"></SmartSqlMap>--> <!-- http资源 -->
<!--<SmartSqlMap Type="Uri" Path="https://smartsql.net/Maps/T_Article.xml" />-->
</SmartSqlMaps>
<!-- 数据Map配置 End -->
</SmartSqlMapConfig>
2.3 表Map配置
2.3.1 Root节点
<SmartSqlMap Scope="Article" xmlns="http://SmartSql.net/schemas/SmartSqlMap.xsd">
...
</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. 让配置工作起来
其实到了这一步一切都顺其自然了。我感觉没有什么可以多讲了。直接上代码了!
using Microsoft.Extensions.DependencyInjection;
using SmartSql;
using SmartSqlSampleChapterOne.Entity;
using System;
using System.Collections.Generic; namespace SmartSqlSampleChapterOne.DataAccess
{
/// <summary>
///
/// </summary>
public class ArticleDataAccess
{
private readonly ISqlMapper _sqlMapper; /// <summary>
///
/// </summary>
/// <param name="sp"></param>
public ArticleDataAccess(IServiceProvider sp)
{
_sqlMapper = sp.GetSmartSql("SmartSqlSampleChapterOne").SqlMapper;
} /// <summary>
/// Insert
/// </summary>
/// <param name="article"></param>
/// <returns></returns>
public long Insert(T_Article article)
{
return _sqlMapper.ExecuteScalar<long>(new RequestContext
{
Scope = "Article",
SqlId = "Insert",
Request = article
});
} /// <summary>
/// Update
/// </summary>
/// <param name="article"></param>
/// <returns></returns>
public int Update(T_Article article)
{
return _sqlMapper.Execute(new RequestContext
{
Scope = "Article",
SqlId = "Update",
Request = article
});
} /// <summary>
/// DyUpdate
/// </summary>
/// <param name="updateObj"></param>
/// <returns></returns>
public int DyUpdate(object updateObj)
{
return _sqlMapper.Execute(new RequestContext
{
Scope = "Article",
SqlId = "Update",
Request = updateObj
});
} /// <summary>
/// Delete
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public int Delete(long id)
{
return _sqlMapper.Execute(new RequestContext
{
Scope = "Article",
SqlId = "Delete",
Request = new { Id = id }
});
} /// <summary>
/// GetById
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public T_Article GetById(long id)
{
return _sqlMapper.QuerySingle<T_Article>(new RequestContext
{
Scope = "Article",
SqlId = "GetEntity",
Request = new { Id = id }
});
} /// <summary>
/// Query
/// </summary>
/// <param name="queryParams"></param>
/// <returns></returns>
public IEnumerable<T_Article> Query(object queryParams)
{
return _sqlMapper.Query<T_Article>(new RequestContext
{
Scope = "Article",
SqlId = "Query",
Request = queryParams
});
} /// <summary>
/// GetRecord
/// </summary>
/// <param name="queryParams"></param>
/// <returns></returns>
public int GetRecord(object queryParams)
{
return _sqlMapper.ExecuteScalar<int>(new RequestContext
{
Scope = "Article",
SqlId = "GetRecord",
Request = queryParams
});
} /// <summary>
/// IsExist
/// </summary>
/// <param name="queryParams"></param>
/// <returns></returns>
public bool IsExist(object queryParams)
{
return _sqlMapper.QuerySingle<bool>(new RequestContext
{
Scope = "Article",
SqlId = "IsExist",
Request = queryParams
});
}
}
}
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) > ;
} /// <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
}) > ;
} /// <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也注入进去。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.IO;
using SmartSql.ConfigBuilder;
using SmartSqlSampleChapterOne.DataAccess; namespace SmartSqlSampleChapterOne
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); services.AddLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Trace);
logging.AddConsole();
}); // register smartsql
services.AddSmartSql(builder =>
{
builder.UseAlias("SmartSqlSampleChapterOne"); // 定义实例别名,在多库场景下适用。
//.UseXmlConfig(ResourceType.File,"MyConfig.xml");
}); // register data access
services.AddSingleton<ArticleDataAccess>(); // register swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("SmartSqlSampleChapterOne", new Info
{
Title = "SmartSqlSample.ChapterOne",
Version = "v1",
Description = "SmartSqlSample.ChapterOne"
});
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SmartSqlSampleChapterOne.xml");
if (File.Exists(filePath)) c.IncludeXmlComments(filePath);
}); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseMvc(); app.UseSwagger(c => { });
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/SmartSqlSampleChapterOne/swagger.json", "SmartSqlSampleChapterOne"); });
}
}
}
Startup
好了!至此项目的大部分元素都做了一个简单介绍。我们来看看最终的运行结果吧。
5. 接口演示
接口预览
添加接口
获取接口
查询接口
6. 结语
本篇文章简单介绍了一下如何使用SmartSql从无到有,完成一个单表的CURD接口实现。但其实SmartSql是一个非常强大的ORM,它还有许多特性没有展开。再接下来的系列文章中。我会一一为大家介绍。
下期预告:使用动态代理实现CURD
SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务的更多相关文章
- idea破解版安装、配置jdk以及建立一个简单的maven工程
idea破解版安装.配置jdk,配置jdk环境变量以及建立一个简单的maven工程 一.idea破解版以及配置文件下载 下载网址:https://pan.baidu.com/s/1yojA51X1RU ...
- 通过myclipse建立一个简单的Hibernate项目(PS:在单元测试中实现数据的向表的插入)
Hibernate的主要功能及用法: Ⅰ.Hibernate封装了JDBC,使Java程序员能够以面向对象的思想对数据库进行操作 Ⅱ.Hibernate可以应用于EJB的J2EE架构,完成数据的持久化 ...
- Django 学习笔记之六 建立一个简单的博客应用程序
最近在学习django时建立了一个简单的博客应用程序,现在把简单的步骤说一下.本人的用的版本是python 2.7.3和django 1.10.3,Windows10系统 1.首先通过命令建立项目和a ...
- Hyperledger Fabric 建立一个简单网络
Building you first network 网络结构: 2个Orgnizations(每个Org包含2个peer节点)+1个solo ordering service 打开fabric-sa ...
- django 建立一个简单的应用
本人的用的版本是python 2.7.3和django 1.10.5,Windows10系统 1.首先通过命令建立项目和app 找到django的安装路径,我的路径是:C:\Python27\Lib\ ...
- 学习用node.js建立一个简单的web服务器
一.建立简单的Web服务器涉及到Node.js的一些基本知识点: 1.请求模块 在Node.js中,系统提供了许多有用的模块(当然你也可以用JavaScript编写自己的模块,以后的章节我们将详细讲解 ...
- 【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement
本blog提供了一个简单的通过JDBC驱动建立JDBC连接例程.并分别通过Statement和PreparedStatement实现对数据库的查询. 在下一篇blog中将重点比較Statement与P ...
- 搭建Vue.js环境,建立一个简单的Vue项目
基于vue-cli快速构建 Vue是近年来比较火的一个前端框架,所以搭建Vue.js环境,要装webpack,vue-cli,Vue 安装webpack命令如下 $ cnpm install webp ...
- 使用go, gin, gorm编写一个简单的curd的api接口
go 是一门非常灵活的语言,既具有静态语言的高性能,又有动态语言的开发速度快的优点,语法也比较简单,下面是通过简单的代码实现了一个简单的增删改查 api 接口 hello world 常规版 新建 d ...
随机推荐
- 解决怎样监听Activity切换
本篇博文在我之前的博文中已经提到了,可是监听Activity切换又能够作为一个单独的内容来叙述,因此这里又单独拿了出来进行赘述. Activity的切换无非有两种.第一种:启动或者创建一个新的Acti ...
- Arrays.sort(a) 自定义排序
Arrays.sort(a) 自定义排序,(需实现接口:Comparable) package com.hd; import java.util.Arrays; class Person imple ...
- ecmall时间的问题
$time1 = date("Y-m-d H:i:s", gmtime()); $time = date("Y-m-d H:i:s", time()); / ...
- 【BZOJ4296】[PA2015]Mistrzostwa BFS
[BZOJ4296][PA2015]Mistrzostwa Description 给定一张n个点m条边的无向图,请找到一个点数最多的点集S,满足:1.对于点集中任何一个点,它至少与d个点集中的点相邻 ...
- OBS桌面视频直播软件/推流工具使用指南
OBS 操作指南 什么是OBS? Open Broadcaster Software 是一款好用的互联网流媒体直播内容输入作软件. OBS使用是否收费? 不收费,这个程序和它的源代码都是免费的. OB ...
- Hibernate基础知识介绍
一.什么是Hibernate? Hibernate,翻译过来是冬眠的意思,其实对于对象来说就是持久化.持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘) ...
- mount available
Mount (computing), the process of making a file system accessible mount (Unix), the utility in Unix- ...
- cocos2d-js v3新特性
1.游戏对象 使用cc.game单例代替了原有的cc.Application以及cc.AppControl 2.属性风格API 旧的API ...
- TCP/IP笔记之OSI和TCP/IP
- java后台判断发布的图片是否存在
x现在已知一个固定格式的图片,判断图片是否存在例如,http://127.0.0.1/image/201709091300.jpg import java.net.URL;import java.ne ...