正文

本文3.0版本文章

本文涉及的内容,同样适用于3.0版本,不用修改。

前言

1、在使用的时候,特别是更新数据的时候,如果不知道哪里有问题,可以查看数据库 和 实体类 的字段,是否大小写一致,比如 name 和 Name

2、在使用Sqlsugar 的 CodeFirst的时候,记得要先重建一个空的数据库,不然会提示错误。

注意:Sqlsugar 5.x 版本已经支持自动创建数据库了,如果你用了最新的版本,可以不用手动创建(加上一行代码 db.DbMaintenance.CreateDatabase(); ),反之需要;

3、要学会使用数据库监控分析器

  书接上文:《从壹开始前后端分离【 .NET Core2.0 Api + Vue 2.0 + AOP + 分布式】框架之六 || API项目整体搭建 6.1 仓储》,我们简单的对整体项目进行搭建,用到了项目中常见的仓储模式+面向接口编程,核心的一共是六层,当然你也可以根据自己的需求进行扩展,比如我在其他的项目中会用到Common层,当然我们这个项目接下来也会有,或者我还会添加Task层,主要是作为定时项目使用,我之前用的是Task Schedule,基本能满足需求。

  在上一节中,我们最后提出了两个问题,不知道大家是否还记得,这里还重新说明一下:

1、如果每个仓储文件都需要把一个一个写出来,至少是四遍,会不会太麻烦,而且无法复用,失去了面向接口编程的意义;

2、每次接口调用的时候,需要引入很多命名空间,比如Blog.Core.IServices;Blog.Core.Services;Blog.Core.Repository等等

  对就是这两个问题,相信聪明的大家也都能看懂,或许还能给出相应的解决办法,比如泛型仓储,比如依赖注入,当然,如果你有更好的办法,欢迎留言,我会把你的想法写下了,让大家一起进步。这里先简单说下问题1中为什么要四遍,仓储模式的基本就是如何将持久化动作和对象获取方式以及领域模型Domain Model结合起来,进一步:如何更加统一我们的语言(Ubiquitous Language),一个整合持久化技术的好办法是仓储Repositories。明白了这个问题,你就知道,定义仓储,首先需要定义IRepository接口(1),然后再Repository中实现(2),接着在IService层中引用这些接口,同时也可以自定义扩展业务逻辑接口(3),最后在Service层中去实现(4),这就是四层。

  问题明白了,我们就要动手做起来,思考了下,如果干巴巴直接写泛型仓储,会比较干涩,所以我考虑今天先把数据持久化做出来,一个轻量级的ORM框架——SqlSugar。

零、今天完成的蓝色部分

0、创建实体模型与数据库

1、实体模型

在上篇文章中,我们说到了仓储模式,所谓仓储,就是对数据的管理,因此,我们就必须要有实体模型,下文说到了 Advertisement ,那就先创建它的实体模型,其他的相关模型,大家自行下载代码即可:

   public class Advertisement
    {
        /// <summary>
        /// ID
        /// </summary>public int Id { get; set; }

        /// <summary>
        /// 广告图片
        /// </summary>public string ImgUrl { get; set; }

        /// <summary>
        /// 广告标题
        /// </summary>public string Title { get; set; }

        /// <summary>
        /// 广告链接
        /// </summary>public string Url { get; set; }

        /// <summary>
        /// 备注
        /// </summary>public string Remark { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime Createdate { get; set; } = DateTime.Now;
    }

2、创建数据库

既然要操作数据库,肯定得先有一个数据库,这里提供了两种方式:

1、Sql语句生成(目前已经不更新,如果一定想要,去群文件下载)

2、通过我的项目,code first 生成,并且里边可以直接 seed data,这样就能生成一个完整的带数据的Database。

具体如何操作可以查看文章——《支持多种数据库 & 快速数据库生成》,如果你感觉麻烦,就自己根据上边的实体模型,自己创建一个数据库。

一、在 IRepository 层设计接口

  还记得昨天我们实现的Sum接口么,今天在仓储接口 IAdvertisementRepository.cs 添加CURD四个接口,首先需要将Model层添加引用,这个应该都会,以后不再细说,如下:

namespace Blog.Core.IRepository
{
    public interface IAdvertisementRepository
    {
        int Sum(int i, int j);

        int Add(Advertisement model);
        bool Delete(Advertisement model);
        bool Update(Advertisement model);
        List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression);

    }
}

编译项目,提示错误,别慌!很正常,因为我们现在只是添加了接口,还没有实现接口。

二、在 Repository 层实现相应接口

当然,我们还是在AdvertisementRepository.cs文件中操作,这里我有一个小技巧,不知道大家是否用到过,因为我比较喜欢写接口,这样不仅可以不暴露核心代码,而且也可以让用户调用的时候,直接看到简单的接口方法列表,而不去管具体的实现过程,这样的设计思路还是比较提倡的,如下图:

你先看到了继承的接口有红色的波浪线,证明有错误,然后右键该接口,点击 Quick Actions and Refactorings...,也就是 快速操作和重构 ,你就会看到VS的智能提示,双击左侧的Implement interface,也就是实现接口,如下图:

Visual Studio真是宇宙第一IDE,没的说 [手动点赞],然后就创建成功了,你就可以去掉throw处理,自定义代码编写了,当然,如果你不习惯或者害怕出错,那就手动写吧,也是很快的。

namespace Blog.Core.Repository
{
    public class AdvertisementRepository : IAdvertisementRepository
    {
        public int Add(Advertisement model)
        {
            throw new NotImplementedException();
        }

        public bool Delete(Advertisement model)
        {
            throw new NotImplementedException();
        }

        public List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression)
        {
            throw new NotImplementedException();
        }

        public int Sum(int i, int j)
        {
            return i + j;
        }

        public bool Update(Advertisement model)
        {
            throw new NotImplementedException();
        }
    }
}

这个时候我们重新编译项目,嗯!意料之中,没有错误,但是具体的数据持久化如何写呢?

三、引用轻量级的ORM框架——SqlSugar

首先什么是ORM, 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。这些概念我就不细说了,自从开发这些年,一直在讨论的问题就是用ADO.NET还是用ORM框架,还记得前几年面试的时候,有一个经理问:

如果一个项目,你是用三层架构ADO,还是用ORM中的EF?

大家可以自由留言,我表示各有千秋吧,一个产品的存在即有合理性,我平时项目中也有ADO,也有EF,不过本系列教程中基于面向对象思想,面向接口思想,当然还有以后的面向切面编程(AOP),还是使用ORM框架,不过是一个轻量级的,EF比较重,我在我其他的项目中用到了.Net MVC 6.0 + EF Code First 的项目,如果大家需要,我也开源出去,放在Github上,请文末留言吧~

  关于ORM有一些常见的框架,如SqlSugar、Dapper、EF、NHeberneit等等,这些我都或多或少的了解过,使用过,至于你要问我为啥用SqlSugar,只要一个原因,作者是中国人,嗯!没错,这里给他打个广告,本系列中的前端框架Vue,也是我们中国的,Vue作者尤雨溪,这里也祝福大家都能有自己的成绩,为国人争光!

扯远了,开始动手引入框架:

开始,我们需要先向 Repository 层中引入SqlSugar,如下:

1)直接在类库中通过Nuget引入 sqlSugarCore,一定是Core版本的!,我个人采用这个办法,因为项目已经比较成型

2)Github下载源码,然后项目引用(点击跳转到Github下载页)

注意:为什么要单独在仓储层来引入ORM持久化接口,是因为,降低耦合,如果以后想要换成EF或者Deper,只需要修改Repository就行了,其他都不需要修改,达到很好的解耦效果

编译一切正常,继续

首先呢,你需要了解下sqlsugar的具体使用方法,http://www.codeisbug.com/Doc/8,你先自己在控制台可以简单试一试,这里就不细说了,如果大家有需要,我可以单开一个文章,重点讲解SqlSugar这一块。

1、在Blog.Core.Repository新建一个sugar文件夹,然后添加两个配置文件,BaseDBConfig.cs 和  DbContext.cs ,这个你如果看了上边的文档,那这两个应该就不是问题。

namespace Blog.Core.Repository
{
    public class BaseDBConfig
    {
        public static string ConnectionString = File.ReadAllText(@"D:\my-file\dbCountPsw1.txt").Trim();

        //正常格式是

        //public static string ConnectionString = "server=.;uid=sa;pwd=sa;database=BlogDB"; 

        //原谅我用配置文件的形式,因为我直接调用的是我的服务器账号和密码,安全起见

    }
}

//DbContext.cs,一个详细的上下文类,看不懂没关系,以后我会详细讲解

 

2、然后在刚刚我们实现那四个方法的AdvertisementRepository.cs中,重写构造函数,编辑统一Sqlsugar实例方法,用到了私有属性,为以后的单列模式做准备。

     private DbContext context;
        private SqlSugarClient db;
        private SimpleClient<Advertisement> entityDB;

        internal SqlSugarClient Db
        {
            get { return db; }
            private set { db = value; }
        }
        public DbContext Context
        {
            get { return context; }
            set { context = value; }
        }
        public AdvertisementRepository() {
            DbContext.Init(BaseDBConfig.ConnectionString);
            context = DbContext.GetDbContext();       db = context.Db;
            entityDB = context.GetEntityDB<Advertisement>(db);
        }

3、正式开始写持久化逻辑代码(注意:我在Model层中,添加了全局的数据类型转换方法,UtilConvert,这样就不用每次都Convert,而且也解决了为空转换异常的bug)

 

最终的仓储持久化是:

    public class AdvertisementRepository : IAdvertisementRepository
    {

        private DbContext context;
        private SqlSugarClient db;
        private SimpleClient<Advertisement> entityDB;

        internal SqlSugarClient Db
        {
            get { return db; }
            private set { db = value; }
        }
        public DbContext Context
        {
            get { return context; }
            set { context = value; }
        }
        public AdvertisementRepository() {
            DbContext.Init(BaseDBConfig.ConnectionString);
            context = DbContext.GetDbContext();       db = context.Db;
            entityDB = context.GetEntityDB<Advertisement>(db);
        }
        public int Add(Advertisement model)
        {
            //返回的i是long类型,这里你可以根据你的业务需要进行处理
            var i = db.Insertable(model).ExecuteReturnBigIdentity();
            return i.ObjToInt();
        }

        public bool Delete(Advertisement model)
        {
            var i =  db.Deleteable(model).ExecuteCommand();
            return i > 0;
        }

        public List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression)
        {
            return entityDB.GetList(whereExpression);

        }

        public int Sum(int i, int j)
        {
            return i + j;
        }

        public bool Update(Advertisement model)
        {
            //这种方式会以主键为条件
            var i =   db.Updateable(model).ExecuteCommand();
            return i > 0;
        }
    }

四、在 IServices 层设计服务接口,并 Service 层实现

这里不细说,记得添加引用,最终的代码是:

namespace Blog.Core.IServices
{
    public interface IAdvertisementServices
    {
        int Sum(int i, int j);
        int Add(Advertisement model);
        bool Delete(Advertisement model);
        bool Update(Advertisement model);
        List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression);
    }
}
namespace Blog.Core.Services
{
    public class AdvertisementServices : IAdvertisementServices
    {
        public IAdvertisementRepository dal = new AdvertisementRepository();
        public int Sum(int i, int j)
        {
            return dal.Sum(i, j);

        }

        public int Add(Advertisement model)
        {
            return dal.Add(model);
        }

        public bool Delete(Advertisement model)
        {
            return dal.Delete(model);
        }

        public List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression)
        {
            return dal.Query(whereExpression);

        }

        public bool Update(Advertisement model)
        {
            return dal.Update(model);
        }

    }
}

都是很简单,如果昨天的Sum方法你会了,这个肯定都会。

五、Controller测试接口

  实现工作,根据id获取数据

  这里为了调试方便,我把权限验证暂时注释掉

  //[Authorize(Policy ="Admin")]

然后修改我们的其中一个Get方法,根据id获取信息

       // GET: api/Blog/5
        /// <summary>
        ///
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "Get")]
        public List<Advertisement> Get(int id)
        {
            IAdvertisementServices advertisementServices = new AdvertisementServices();

            return advertisementServices.Query(d => d.Id == id);
        }
        

接下来运行调试,在我们接口文档中,直接点击调试

得到的结果是如果,虽然是空的,但是返回结果http代码是200,因为表中没数据嘛

六、结语

  好啦,今天的讲解就到这里,你简单的了解了什么是ORM,以及其中的SqlSugar,然后呢,仓储模式的具体使用,最后还有真正的连接数据库,获取到数据,下一节中,我们继续来解决两大问题,来实现泛型仓储。

七、CODE

https://github.com/anjoy8/Blog.Core.git

https://gitee.com/laozhangIsPhi/Blog.Core

Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之七 || API项目整体搭建 6.2 轻量级ORM的更多相关文章

  1. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之七 || API项目整体搭建 6.2 轻量级ORM

    更新 1.在使用的时候,特别是更新数据的时候,如果不知道哪里有问题,可以查看数据库 和 实体类 的字段,是否大小写一致,比如 name 和 Name 2.在使用Sqlsugar 的 CodeFirst ...

  2. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...

  3. Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探

    本文梯子 本文3.0版本文章 更新 代码已上传Github+Gitee,文末有地址 零.今天完成的绿色部分 一.依赖注入的理解和思考 二.常见的IoC框架有哪些 1.Autofac+原生 2.三种注入 ...

  4. Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储+服务+抽象接口模式

    本文梯子 本文3.0版本文章 前言 零.完成图中的粉色部分 2019-08-30:关于仓储的相关话题 一.创建实体Model数据层 二.设计仓储接口与其实现类 三.设计服务接口与其实现类 四.创建 C ...

  5. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之四 || Swagger的使用 3.2

    本文梯子 本文3.0版本文章 前言 一.swagger的一般用法 0.设置swagger页面为首页——开发环境 1.设置默认直接首页访问 —— 生产环境 2.为接口添加注释 3.对 Model 也添加 ...

  6. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储模式

    前言 1.@LearningCoding 小伙伴关于用Sqlsugar在mysql数据库上的研究成果: sqlsugarcore支持mysql等数据库,在DbContext里面只需要设置dbtype为 ...

  7. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之三 || Swagger的使用 3.1

    本文梯子 本文3.0版本文章 常见问题 1.Bug调试 2.经常有小伙伴遇到这个错误 3.路由重载 一.为什么使用Swagger 二.配置Swagger服务 1.引用Nuget包 2.配置服务 3.启 ...

  8. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之二 || 后端项目搭建

    本文梯子 前言 1..net core 框架性能测试 2..net core 执行过程 3.中间件执行过程 4.AOP切面 5.整体框架结构与数据库表UML 一.创建第一个Core 1.SDK 安装 ...

  9. Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之五 || Swagger的使用 3.3 JWT权限验证【必看】

    本文梯子 本文3.0版本文章 前言 1.如何给接口实现权限验证? 零.生成 Token 令牌 一.JWT ——自定义中间件 0.Swagger中开启JWT服务 1:API接口授权策略 2.自定义认证之 ...

随机推荐

  1. [译]Vulkan教程(08)逻辑设备和队列

    [译]Vulkan教程(08)逻辑设备和队列 Introduction 入门 After selecting a physical device to use we need to set up a  ...

  2. JS如何判断鼠标滚轮向上还是向下滚动

    前几天偶然看到某前端群有人在问:JS如何判断鼠标滚轮向上还是向下滚动? 我想了想,有点蒙蔽,心想难道不是用scrollTop来判断吗? 但我不确定,也出于好奇心,于是开始了一番探索 思路:通过even ...

  3. 国产处理器的逆袭机会——RISC-V

    前言 今天天气阴沉,刚才又下起了小雨,温度骤降,前几天脱下的秋裤,今天又穿上了,这天气真是变化无常.上周六(4.20)参加了一场关于RSIC-V的技术沙龙,第一次真正了解了RISC-V架构,正好今天不 ...

  4. ASP.NET Core Web 应用程序开发期间部署到IIS自定义主机域名并附加到进程调试

    想必大家之前在进行ASP.NET Web 应用程序开发期间都有用到过将我们的网站部署到IIS自定义主机域名并附加到进程进行调试. 那我们的ASP.NET Core Web 应用程序又是如何部署到我们的 ...

  5. Grafana+Prometheus 监控 MySQL

    转自:Grafana+Prometheus 监控 MySQL 架构图 环境 IP 环境 需装软件 192.168.0.237 mysql-5.7.20 node_exporter-0.15.2.lin ...

  6. 搜索某个目录下所有jar包中的mapper目录下的xml文件

    rm -rf /mapper/* find /data/app/app-*/lib ! -path "*xnpush*" ! -path "*portal*" ...

  7. HTML基础——表单的应用

    1.表单的构成 一个完整的表单由表单控件(表单元素).提示信息和表单域3个部分构成. 表单控件:包含了具体的表单功能项,如单行文本输入框.密码输入框.复选框.提交按钮.搜索框等. 提示信息:一个表单中 ...

  8. 利用Azure虚拟机安装Dynamics 365 Customer Engagement之十:为SQL Server配置Always On

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  9. 通过 RxSwift 优雅使用 NotificationCenter

    原文 纯粹的官方代码使用NotificationCenter真的很难用,但是有了RxSwift,就变得方便了很多. 修改 Podfile,通过pod引入RxSwift pod 'RxSwift' po ...

  10. 剑指offer 28:字符串的排列

    题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述 输入 ...