SmartSql使用教程(2)—使用动态代理实现CURD
一、引言
接着上一篇的教程,本章我们继续讲smartsql。今天的主题是动态仓储。
老规矩,先上一个项目结构
从第二章开始。我们将原来的单一项目做了一个分离。方便之后的更新。
在这个结构中。原本上一章的dataaccess没有了。取而代之的是repository。这个就是动态仓储的项目。接下来我们从这个repository项目开始说。这也是动态仓储的核心。
二、repository项目
1. nuget依赖
smartsql有一个独立的动态仓储库,即:smartsql.dyrepository。如果你想使用动态仓储,引用它就行啦。
2. 第一个仓储接口
引用完库,接下来就是创建我们的第一个仓储接口—iarticlerepository。废话不到,先上代码再一一解释。
1 using smartsql.dyrepository; 2 using smartsql.dyrepository.annotations; 3 using smartsqlsamplechaptertwo.entity; 4 using system.data; 5 6 namespace smartsqlsamplechaptertwo.repository 7 { 8 [sqlmap(scope = "customscope")] 9 public interface iarticlerepository : irepository<t_article, long> 10 { 11 [statement(commandtype = commandtype.text, execute = executebehavior.executescalar, id = "offline")] 12 int offlinearticle([param("id", fieldtype = typeof(long))] long articleid); 13 14 [statement(sql = "update t_article set status = 1 where id = @id")] 15 int onlinearticle([param("id")] long article); 16 } 17 }
2.1 默认接口 irepository
看完代码是不是发现和上一章的dataaccess有很大的区别,那些curd的方法都没有了。
这是smartsql内置的一些默认接口,它包括以下这些接口,这些接口基本可以满足大部分普通业务场景了。
1 int insert(tentity entity); 2 3 int update(tentity entity); 4 5 [statement(id = "update")] 6 int dyupdate(object dyobj); 7 8 int delete(object reqparams); 9 10 [statement(id = "delete")] 11 int deletebyid([param("id")] tprimary id); 12 13 tentity getentity(object reqparams); 14 15 [statement(id = "getentity")] 16 tentity getbyid([param("id")] tprimary id); 17 18 [statement(execute = executebehavior.executescalar)] 19 int getrecord(object reqparams); 20 21 ilist<tentity> querybypage(object reqparams); 22 23 ilist<tentity> query(object reqparams); 24 25 [statement(execute = executebehavior.executescalar)] 26 bool isexist(object reqparams);
2.2 sqlmap特性
这个特性是用于指定scope的配置。这个对应于map中的scope属性。这里我定义了“customscope”。那对应的map中也将与之对应。如下图:
2.3 statement特性
这个特性略微有点复杂,其中包含了6个属性,接下来我们一个个看。
2.3.1 scope
这个特性和sqlmap的scope作用是一样的。区别在于statement的级别更高。
2.3.2 id
指定此函数所使用的statement。依据是id。例:
// 接口定义 [statement(id = "testid")] int customstatementid();
<!-- statement定义 --> <statement id="testid"> db script... </statement>
2.3.3 execute
execute是一个executebehavior枚举,用于指定此函数执行sql脚本的方式。
auto | orm自动识别 |
execute | 返回影响行数,主要用于执行写操作。 |
executescalar | 返回第一行第一列的数据,主要用于返回自增主键和获取结果数 |
query | 返回list |
querysingle | 返回第一行数据 |
getdatatable | 返回datatable |
getdataset | 返回dataset |
2.3.4 sql
特殊场景下,可以直接使用此属性定义sql脚本,而不用配置sqlmap。如iarticlerepository的onlinearticle定义。
2.3.5 commandtype
这个属性是ado.net的commandtype枚举。作用也完全相同
2.3.6 sourcechoice
指定数据源,可以指定write或read。
3. startup
在上一章节中,我们在startup中注册了smartsql,现在我们要继续注册动态仓储。代码也很简单,只要在addsmart方法完成后继续调用addrepositoryfromassembly即可。如下:
services.addsmartsql(builder => { builder.usealias("smartsqlsamplechaptertwo"); // 定义实例别名,在多库场景下适用。 //.usexmlconfig(resourcetype.file,"myconfig.xml"); }).addrepositoryfromassembly(options => { // smartsql实例的别名 options.smartsqlalias = "smartsqlsamplechaptertwo"; // 仓储接口所在的程序集全称 options.assemblystring = "smartsqlsamplechaptertwo.repository"; // 筛选器,根据接口的type筛选需要的仓储 options.filter = type => type.fullname.contains("sample"); // scope模板,默认是"i{scope}repository" options.scopetemplate = "i{scope}repository"; });
这个方法中会抛出一个assemblyautoregisteroptions,方便用户注册指定的仓储。
4. controller的变化
在sample中,我们直接让controller引用了repository,实际场景中。我们可以在任何需要仓储的地方引用仓储。代码如下:
using microsoft.aspnetcore.mvc; using smartsqlsamplechaptertwo.entity; using smartsqlsamplechaptertwo.repository; using system.collections.generic; namespace smartsqlsamplechaptertwo.api.controllers { /// <summary> /// /// </summary> [route("[controller]/[action]")] public class articlecontroller : controller { private readonly iarticlerepository _articlerepository; /// <summary> /// constructor /// </summary> /// <param name="articlerepository"></param> public articlecontroller(iarticlerepository articlerepository) { _articlerepository = articlerepository; } /// <summary> /// /// </summary> /// <param name="article"></param> /// <returns></returns> [httppost] public t_article add([frombody] t_article article) { article.id = _articlerepository.insert(article); return article; } /// <summary> /// /// </summary> /// <param name="id"></param> /// <returns></returns> [httpget] public t_article get([fromquery] long id) { return _articlerepository.getbyid(id); } /// <summary> /// /// </summary> /// <param name="article"></param> /// <returns></returns> [httppost] public bool update([frombody] t_article article) { return _articlerepository.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 _articlerepository.dyupdate(new { id = id, status = status }) > 0; } /// <summary> /// /// </summary> /// <param name="id"></param> /// <returns></returns> [httpget] public bool isexist([fromquery] long id) { return _articlerepository.isexist(new { id = id }); } /// <summary> /// /// </summary> /// <param name="key"></param> /// <returns></returns> [httpget] public ienumerable<t_article> query([fromquery] string key = "") { return _articlerepository.query(new { title = key }); } /// <summary> /// /// </summary> /// <param name="id"></param> /// <returns></returns> [httpget] public int offline([fromquery] long id) { return _articlerepository.offlinearticle(id); } /// <summary> /// /// </summary> /// <param name="id"></param> /// <returns></returns> [httpget] public int online([fromquery] long id) { return _articlerepository.onlinearticle(id); } } }
可以注意到的是,除了把dataaccess变成了repository。其他的代码几乎没有改动。最后我还添加了仓储自定义的接口的调用。
5. 结语
今天,我们了解了动态仓储的使用。它是一个非常方便的特性,可以非常显著的提升我们写代码的效率,减少一定的代码量,避免了很多“体力活”。让我们专注于业务!
下期预告:smartsql中的事务,及aop的使用
推荐阅读
-
在Python中使用M2Crypto模块实现AES加密的教程
-
Java JDK动态代理(AOP)的实现原理与使用详析
-
matlab2c使用c++实现matlab函数系列教程-binostat函数
-
matlab2c使用c++实现matlab函数系列教程-cumprod函数
-
使用JAVA中的动态代理实现数据库连接池 JavaSQLJDBC应用服务器互联网
-
SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务
-
matlab2c使用c++实现matlab函数教程系列-blkdiag函数
-
SmartSql使用教程(2)—使用动态代理实现CURD
-
在Python下使用Txt2Html实现网页过滤代理的教程
-
matlab2c使用c++实现matlab函数系列教程-geomean函数