正文

本文3.0版本文章

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

前言

  书接上文:前几回文章中,我们花了三天的时间简单了解了下接口文档Swagger框架,已经完全解放了我们的以前的Word说明文档,并且可以在线进行调试,而且当项目开始之中,我们可以定义一些空的接口,或者可以返回假数据,这样真正达到了前后端不等待的缺陷,还是很不错的,当然,这离我说的前后端分离还是相差甚远,今天呢,我们就简单搭建下我们的项目架构。

  本项目是我自己的一个真实项目,数据都是真实的,之前搭建过一个MVC + EF Code First的项目,本项目就是基于这个了,前一段时间我已经搭建起来了,是这样的,本系列教程会重新开始。

零、完成图中的粉色部分

先简单解释下各层之间的调用关系:

除了项目对外暴露的是 Api 展示层,和核心的实体 Model 层外,

仓储模块(作为一个数据库管理员,直接操作数据库,实体模型):

BaseRepository(基类仓储) 继承实现了 接口IBaseRepository,这里放公共的方法,
AdvertisementRepostitory 继承 BaseRepository<Advertisement>, IAdvertisementRepository

Service模块(处理业务逻辑,可以直接使用ViewModel视图模型):

BaseService 调用 BaseRepository,同时继承 IBaseService
AdvertisementServices  继承   BaseServices<Advertisement>, IAdvertisementServices

2019-08-30:关于仓储的相关话题

很多人都有一个这样的想法,仓储就是Dal层?我这里简单说一下两者的区别(我Blog.Core项目可能不是体现的出来,DDD可能更好理解):

1、仓储是一种模式,可以单建一层,也可以放到基础设施层,

而Dal是三层架构种的某一层,是一个架构

2、仓储官方的定义,他是一个管理者,去管理实体对象和ORM映射对象的一个集合,是ORM操作db,

而Dal就是完完全全的操作db数据库了,

请注意,不要把 Sqlsugar 当成三层中的 sqlhelper,不一样!

3、仓储更多的是一个聚合,在下一个系列DDD中,我们说到了一个概念,一个聚合的划分其实就是一个仓储。

4、然后我们进一步细化,一个仓储 = 一个聚合 = 有一个聚合根 = 一个微服务!

多个微服务之间交互,就是通过聚合根来的。

一、创建实体Model数据层

  其中,Models文件夹中,存放的是整个项目的数据库表实体类,这里是手动创建的,当然也可以自动创建,在以后的文章中我会提到,用到的是SqlSugar的T4创建,这里先埋一个伏笔。

提示:这个伏笔已经完成,地址《三十二║ 四种方法快速实现项目的半自动化搭建

  然后,VeiwModels文件夹,是存放的DTO实体类,在开发中,一般接口需要接收数据,返回数据,我之前都是这么红果果的使用的,后来发现弊端很大,不仅把重要信息暴露出去(比如手机号等),还对数据造成冗余(比如我需要接收用户的生日,还需要具体的年、月、日这就是三个字段,当然您也可以手动拆开,这只是一个栗子,所以不能直接用数据库实体类接收),就用到了DTO类的转换,但是频繁的转换又会麻烦,别慌,以后的文章中,我们会引用AutoMapper来自动转换,这里再买一个伏笔。

提示:这个伏笔已经完成,地址《十三 || DTOs 对象映射使用

  最后的是MessageModel和TableModel,大家也基本一看就能明白,因为在前端接口中,需要固定的格式,以及操作,不能把数据直接发出去,会报错,在以后的Vue开发中,会提到这个,这里又买了一个伏笔。 如下:

 /// <summary>
    /// 通用返回信息类
    /// </summary>
    public class MessageModel<T>
    {
        /// <summary>
        /// 操作是否成功
        /// </summary>
        public bool Success { get; set; }
        /// <summary>
        /// 返回信息
        /// </summary>
        public string Msg { get; set; }
        /// <summary>
        /// 返回数据集合
        /// </summary>
        public List<T> Data { get; set; }

    }

整个项目运行,没错,继续创建下一层。

二、设计仓储接口与其实现类

创建Blog.Core.IRepository和 Blog.Core.Repository 仓储层:

  这里简单说下仓储层:repository就是一个管理数据持久层的,它负责数据的CRUD(Create, Read, Update, Delete) service layer是业务逻辑层,它常常需要访问repository层。有网友这么说:Repository(仓储):协调领域和数据映射层,利用类似与集合的接口来访问领域对象。Repository 是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository 是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。

  我们定义了IRepository层,提供了所有的操作接口,今天搭建框架,我简单地写一个实例,明天我们将把所有的方法嵌套进去。

  在 IAdvertisementRepository.cs 中,添加一个求和接口

  

   public interface IAdvertisementRepository
    {
        int Sum(int i, int j);
    }

  然后再在 AdvertisementRepository.cs 中去实现该接口,记得要添加引用,这个应该都会,就不细说了。  

    public class AdvertisementRepository : IAdvertisementRepository
    {
        public int Sum(int i, int j)
        {
            return i + j;
        }
    }

   运行项目,一起正常,继续往下。

三、设计服务接口与其实现类

创建 Blog.Core.IServices 和 Blog.Core.Services 业务逻辑层,就是和我们平时使用的三层架构中的BLL层很相似:

  Service层只负责将Repository仓储层的数据进行调用,至于如何是与数据库交互的,它不去管,这样就可以达到一定程度上的解耦,假如以后数据库要换,比如MySql,那Service层就完全不需要修改即可,至于真正意义的解耦,还是得靠依赖注入,这下一节我们会讲到。

  这里在 IAdvertisementServices 中添加接口

  

namespace Blog.Core.IServices
{
    public interface IAdvertisementServices
    {
        int Sum(int i, int j);
    }
}

  然后再在 AdvertisementServices 中去实现该接口

 public class AdvertisementServices : IAdvertisementServices
    {
        IAdvertisementRepository dal = new AdvertisementRepository();

    public int Sum(int i, int j)
        {
            return dal.Sum(i, j);

        }
    }

  注意!这里是引入了三个命名空间

using Blog.Core.IRepository;
using Blog.Core.IServices;

using Blog.Core.Repository;

四、创建 Controller 接口调用

  将系统默认的ValueController删除,手动添加一个BlogController控制器,可以选择一个空的,也可以选择一个带有默认读写实例的。如下:

  

  [Produces("application/json")]
    [Route("api/Blog")]
    [Authorize(Policy ="Admin")]
    public class BlogController : Controller
    {
        // GET: api/Blog
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET: api/Blog/5
        [HttpGet("{id}", Name = "Get")]
        public string Get(int id)
        {
            return "value";
        }

        // POST: api/Blog
        [HttpPost]
        public void Post([FromBody]string value)
        {
        }

        // PUT: api/Blog/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE: api/ApiWithActions/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }

  接下来,在应用层添加服务层的引用

using Blog.Core.IServices;
using Blog.Core.Services;

  然后,改写Get方法

 ·······// GET: api/Blog
        /// <summary>
        /// Sum接口
        /// </summary>
        /// <param name="i">参数i</param>
        /// <param name="j">参数j</param>
        /// <returns></returns>
        [HttpGet]
        public int Get(int i,int j)
        {
            IAdvertisementServices advertisementServices = new AdvertisementServices();
            return advertisementServices.Sum(i,j);
        }

  F5 运行项目,调试如下:

  天呀!出错辣!别慌,还记得昨天咱们加的权限么,嗯!就是那里,手动模拟登陆,获取Token,注入,不会的可以看上一篇,然后再执行,结果:

  

五、结语

  好啦,今天的工作暂时到这里了,你可以看到整体项目的搭建,结构,如何引用,如何测试等,当然,这里还是有很多小问题,比如:

  ·如果每个仓储都需要这么写,至少是四遍,会不会太麻烦;

  ·每次Controller接口调用,需要引入很多命名空间

  ·等等等等

  这些问题,下一节我们都会带大家一起去慢慢解决!

六、Github && Gitee

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

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

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

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

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

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

    本文梯子 本文3.0版本文章 前言 零.今天完成的蓝色部分 0.创建实体模型与数据库 1.实体模型 2.创建数据库 一.在 IRepository 层设计接口 二.在 Repository 层实现相应 ...

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

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

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

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

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

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

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

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

  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. IT兄弟连 HTML5教程 CSS3揭秘 CSS3属性4

    7  多列布局属性 通过CSS3,开发人员能够创建多列来对文本进行布局.在CSS2时代,对于多列布局的设计,大多采用浮动布局和绝对定位布局两种方式.浮动布局比较灵活,但是需要编写大量的附加样式代码,而 ...

  2. C++入门到理解之文件操作(文本文件的读写+二进制文件的读写)

    原文地址http://www.javayihao.top/detail/168 一:概述 1.程序在运行中产生的数据都是临时数据,程序一旦运行结束会被释放,可以通过文件相关的操作将数据持久保存. 2. ...

  3. 【LeetCode】6. Z 字形变换

    题目 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L   C   ...

  4. js获取时间,循环执行任务,延迟执行任务

    一.获取时间 核心方法创建一个时间对象:new Date() 时间对象相关操作 时间对象.函数名 函数名 功能 getYear() 获取四位数的年份 getMonth() 获取2位数的月数, 这个是从 ...

  5. docker postgres使用

    1.拉取镜像文件docker pull postgres 2.容器后台进程运行,向外暴露32769端口 docker run -it --name mypostgres -p 32769:5432 - ...

  6. 从华为“鸿蒙”备胎看IT项目建设

    别误会啊,本文并不在讲大家在做IT项目建设的时候学华为做一个备胎系统,以防正主系统崩掉之后能够及时替换到备胎系统里面,不影响业务. 前段时间华为被美帝制裁,然后各家组织对华为各种限制.然而华为整体布局 ...

  7. Android8.1 源码修改之通过黑名单屏蔽系统短信功能和来电功能

    前言 之前写过一篇Android6.0 的屏蔽系统短信功能和来电功能,具体看这里 同样的最近有个新需求,需要将8.1 设备的来电功能和短信功能都屏蔽掉,特殊产品就是特殊定制,那就开始吧. 屏蔽短信功能 ...

  8. volatile简记

    volatile指出变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错,也就是在使用变量时必须从它的地址中重新读取.

  9. 安装docker并部署web项目

    一.docker简介 1.docker定义:docker是一个用来装应用的容器,就像杯子可以装水,笔筒可以装笔,书包可以放书一样.你可以把“Hello World!”放到docker中,也可以把网站放 ...

  10. MySQL 数据库查询数据,过滤重复数据保留一条数据---(MySQL中的row_number变相实现方法)

    转自: http://www.maomao365.com/?p=10564 摘要: 下文讲述MySQL数据库查询重复数据时,只保留一条数据的方法 实现思路: 在MySQL数据库中没有row_numbe ...