• 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 }
    IArticleRepository

    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脚本的方式。

    ExecuteBehavior
    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);
            }
        }
    }
    ArticleController

      可以注意到的是,除了把DataAccess变成了Repository。其他的代码几乎没有改动。最后我还添加了仓储自定义的接口的调用。

    5. 结语

      今天,我们了解了动态仓储的使用。它是一个非常方便的特性,可以非常显著的提升我们写代码的效率,减少一定的代码量,避免了很多“体力活”。让我们专注于业务!

    示例代码链接在这里

     

    下期预告:SmartSql中的事务,及AOP的使用

  • 相关阅读:
    未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0或2.0.0.0
    解决本地调用office组件成功,但是发布到IIS中出现的错误(检索COM类工厂中CLSID为{00024500-0000-0000-C000-000000000046}的组件时失败)
    未能找到类型或命名空间名称“Coco”(是否缺少 using 指令或程序集引用)
    SQL截取字段字符串的方法
    C# 128位AES 加密解密 (转)
    检索 COM 类工厂中 CLSID 为 {13C28AD0-F195-4319-B7D7-A1BDAA329FB8} 的组件时失败,原因是出现以下错误: 80040154
    js 获取时间比较全,留备用(zhuan)
    windows之如何把iso文件转换为VHD文件
    python之三行代码发送邮件
    RobotFramework第二篇之web自动化
  • 原文地址:https://www.cnblogs.com/noahji/p/10877277.html
Copyright © 2020-2023  润新知