2020/01/29, ASP.NET Core 3.1, VS2019

摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构【8.3-编写角色业务的增删改】

编写最简单的增删改业务,涉及到DI依赖注入的使用、AutoMapper的使用、工作单元与仓储的使用、雪花Id的生成

文章目录

此分支项目代码

本章节介绍了编写最简单的增删改查业务,涉及到DI依赖注入的使用、AutoMapper的使用、工作单元与仓储的使用

类库添加引用

MS.Services类库添加对MS.Models项目的引用

BaseService

MS.Services类库中添加BaseService.cs类:

using AutoMapper;
using MS.Common.IDCode;
using MS.DbContexts;
using MS.UnitOfWork; namespace MS.Services
{
public interface IBaseService
{
}
public class BaseService : IBaseService
{
public readonly IUnitOfWork<MSDbContext> _unitOfWork;
public readonly IMapper _mapper;
public readonly IdWorker _idWorker; public BaseService(IUnitOfWork<MSDbContext> unitOfWork, IMapper mapper, IdWorker idWorker)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
_idWorker = idWorker;
}
}
}

说明:

  • 新建了IBaseService接口,后面新建的服务接口都要继承自该接口
  • 新建了BaseService类,实现了IBaseService接口
  • 可以看到BaseService类中,使用构造函数的方式依赖注入得到了IUnitOfWork _unitOfWork、IMapper _mapper、IdWorker _idWorker,并且是public类型,所以继承BaseService的类都可以直接使用父类的这三个成员

RoleService

MS.Services类库中新建Role文件夹,在该文件夹下新建IRoleService.csRoleService.cs类,注意我这里两个类的命名空间都改为namespace MS.Services,而不是默认的namespace MS.Services.Role

IRoleService接口

修改IRoleService为public类型的interface接口,继承自IBaseService,并添加Create、Update、Delete三个方法:

using MS.Entities;
using MS.Models.ViewModel;
using MS.WebCore.Core;
using System.Threading.Tasks; namespace MS.Services
{
public interface IRoleService : IBaseService
{
Task<ExecuteResult<Role>> Create(RoleViewModel viewModel);
Task<ExecuteResult> Update(RoleViewModel viewModel);
Task<ExecuteResult> Delete(RoleViewModel viewModel);
}
}

RoleService实现

修改RoleService为public类型,继承自BaseService和IRoleService接口,然后使用快速操作生成构造函数和实现接口

接下来开始实现新增Role的业务方法:

public async Task<ExecuteResult<Role>> Create(RoleViewModel viewModel)
{
ExecuteResult<Role> result = new ExecuteResult<Role>();
//检查字段
if (viewModel.CheckField(ExecuteType.Create, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
{
return result.SetFailMessage(checkResult.Message);
}
using (var tran = _unitOfWork.BeginTransaction())//开启一个事务
{
Role newRow = _mapper.Map<Role>(viewModel);
newRow.Id = _idWorker.NextId();//获取一个雪花Id
newRow.Creator = 1219490056771866624;//由于暂时还没有做登录,所以拿不到登录者信息,先随便写一个后面再完善
newRow.CreateTime = DateTime.Now;
_unitOfWork.GetRepository<Role>().Insert(newRow);
await _unitOfWork.SaveChangesAsync();
await tran.CommitAsync();//提交事务 result.SetData(newRow);//添加成功,把新的实体返回回去
}
return result;
}

说明:

  • 异步方法要加上async标记
  • 执行添加之前,先进行了字段检查,如果不通过,则返回错误信息
  • 使用了var tran = _unitOfWork.BeginTransaction()开启了事务,如果遇到异常,会自动回滚,如果不需要使用事务,可以去除,这里只是顺带演示下事务的使用方法
  • 使用了_mapper.Map方法把字段从ViewModel映射到实体类中
  • _idWorker.NextId()方法获取一个雪花Id
  • 由于还没有做登录,所以没有创建者信息,所以先随便写了一个,等做了登录之后再修改
  • 这里方法内部没有做trycatch捕获异常处理,之后会使用AOP拦截器,拦截业务层的每个方法,统一进行业务异常捕获处理

WebApi中调用Service

MS.WebApi应用程序中,RoleController.cs类中,添加RoleService接口,并在Post中调用Create方法:

//using MS.Services;
//以上代码添加到using引用
public class RoleController : ControllerBase
{
private readonly IRoleService _roleService; public RoleController(IRoleService roleService)
{
_roleService = roleService;
} [HttpPost]
public async Task<ExecuteResult> Post(RoleViewModel viewModel)
{
return await _roleService.Create(viewModel);
}
}

说明:

  • 这里依然使用了构造函数依赖注入获取一个接口服务
  • 接口设计满足Restful规范

将接口服务添加到依赖注入

MS.WebApi应用程序中,在Startup.cs类的ConfigureServices方法中追加:

//using MS.Services;
//以上代码添加到using
//注册IBaseService和IRoleService接口及对应的实现类
services.AddScoped<IBaseService, BaseService>();
services.AddScoped<IRoleService, RoleService>();

测试

完成后启动项目,打开Postman调试接口:

可以看到接口调用成功(也可以看到在控制台中有EntityFrameworkCore执行的sql语句)

在数据库中看到新增的记录:

再重复调用一次接口,则会提示角色名称已存在:

完整的增删改角色业务代码:

using AutoMapper;
using MS.Common.IDCode;
using MS.DbContexts;
using MS.Entities;
using MS.Models.ViewModel;
using MS.UnitOfWork;
using MS.WebCore.Core;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks; namespace MS.Services
{
public class RoleService : BaseService, IRoleService
{
public RoleService(IUnitOfWork<MSDbContext> unitOfWork, IMapper mapper, IdWorker idWorker) : base(unitOfWork, mapper, idWorker)
{
} public async Task<ExecuteResult<Role>> Create(RoleViewModel viewModel)
{
ExecuteResult<Role> result = new ExecuteResult<Role>();
//检查字段
if (viewModel.CheckField(ExecuteType.Create, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
{
return result.SetFailMessage(checkResult.Message);
}
using (var tran = _unitOfWork.BeginTransaction())//开启一个事务
{
Role newRow = _mapper.Map<Role>(viewModel);
newRow.Id = _idWorker.NextId();//获取一个雪花Id
newRow.Creator = 1219490056771866624;//由于暂时还没有做登录,所以拿不到登录者信息,先随便写一个后面再完善
newRow.CreateTime = DateTime.Now;
_unitOfWork.GetRepository<Role>().Insert(newRow);
await _unitOfWork.SaveChangesAsync();
await tran.CommitAsync();//提交事务 result.SetData(newRow);//添加成功,把新的实体返回回去
}
return result;
} public async Task<ExecuteResult> Delete(RoleViewModel viewModel)
{
ExecuteResult result = new ExecuteResult();
//检查字段
if (viewModel.CheckField(ExecuteType.Delete, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
{
return checkResult;
}
_unitOfWork.GetRepository<Role>().Delete(viewModel.Id);
await _unitOfWork.SaveChangesAsync();//提交
return result;
} public async Task<ExecuteResult> Update(RoleViewModel viewModel)
{
ExecuteResult result = new ExecuteResult();
//检查字段
if (viewModel.CheckField(ExecuteType.Update, _unitOfWork) is ExecuteResult checkResult && !checkResult.IsSucceed)
{
return checkResult;
} //从数据库中取出该记录
var row = await _unitOfWork.GetRepository<Role>().FindAsync(viewModel.Id);//在viewModel.CheckField中已经获取了一次用于检查,所以此处不会重复再从数据库取一次,有缓存
//修改对应的值
row.Name = viewModel.Name;
row.DisplayName = viewModel.DisplayName;
row.Remark = viewModel.Remark;
row.Modifier = 1219490056771866624;//由于暂时还没有做登录,所以拿不到登录者信息,先随便写一个后面再完善
row.ModifyTime = DateTime.Now;
_unitOfWork.GetRepository<Role>().Update(row);
await _unitOfWork.SaveChangesAsync();//提交 return result;
}
}
}

完整的接口代码:

using Microsoft.AspNetCore.Mvc;
using MS.Models.ViewModel;
using MS.Services;
using MS.WebCore.Core;
using System.Threading.Tasks; namespace MS.WebApi.Controllers
{
[Route("[controller]")]
[ApiController]
public class RoleController : ControllerBase
{
private readonly IRoleService _roleService; public RoleController(IRoleService roleService)
{
_roleService = roleService;
} [HttpPost]
public async Task<ExecuteResult> Post(RoleViewModel viewModel)
{
return await _roleService.Create(viewModel);
} [HttpPut]
public async Task<ExecuteResult> Put(RoleViewModel viewModel)
{
return await _roleService.Update(viewModel);
} [HttpDelete]
public async Task<ExecuteResult> Delete(long id)
{
return await _roleService.Delete(new RoleViewModel { Id = id });
}
}
}

更新接口测试:

删除接口测试:

项目完成后,如下图所示

ASP.NET Core搭建多层网站架构【8.3-编写角色业务的增删改】的更多相关文章

  1. ASP.NET Core搭建多层网站架构【0-前言】

    2020/01/26, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构 目录 0-前言 1-项目结构分层建立 2-公共基 ...

  2. ASP.NET Core搭建多层网站架构【1-项目结构分层建立】

    2020/01/26, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[1-项目结构分层建立] 文章目录 此分支项目代码 ...

  3. ASP.NET Core搭建多层网站架构【2-公共基础库】

    2020/01/28, ASP.NET Core 3.1, VS2019,Newtonsoft.Json 12.0.3, Microsoft.AspNetCore.Cryptography.KeyDe ...

  4. ASP.NET Core搭建多层网站架构【3-xUnit单元测试之简单方法测试】

    2020/01/28, ASP.NET Core 3.1, VS2019, xUnit 2.4.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[3-xUnit单元测试 ...

  5. ASP.NET Core搭建多层网站架构【4-工作单元和仓储设计】

    2020/01/28, ASP.NET Core 3.1, VS2019, Microsoft.EntityFrameworkCore.Relational 3.1.1 摘要:基于ASP.NET Co ...

  6. ASP.NET Core搭建多层网站架构【5-网站数据库实体设计及映射配置】

    2020/01/29, ASP.NET Core 3.1, VS2019, EntityFrameworkCore 3.1.1, Microsoft.Extensions.Logging.Consol ...

  7. ASP.NET Core搭建多层网站架构【6-注册跨域、网站核心配置】

    2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...

  8. ASP.NET Core搭建多层网站架构【7-使用NLog日志记录器】

    2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...

  9. ASP.NET Core搭建多层网站架构【8.1-使用ViewModel注解验证】

    2020/01/29, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[8.1-使用ViewModel注解验证] 使用V ...

随机推荐

  1. 算法导论2-4 O(nlgn)时间复杂度求逆序对

    def mergesort(nums,le,ri): if le>ri-2: return 0 mi=le+(ri-le)//2 a=mergesort(nums,le,mi) b=merges ...

  2. Android开发 UI布局

    Android开发 UI布局一.线性布局LinearLayout 什么是线性布局? 其实呢,线性布局就是把所有的孩子摆在同一条线上 <?xml version="1.0" e ...

  3. CSS的布局之文档流,与行内/块级元素的延伸

    文档流,即(position:stiatic),是html布局机制的默认状态. 文档流在排列的过程中,块级元素从上到下,行内元素,从左到右. ·块级元素 <div> <h系列> ...

  4. JQuery/JS插件 jsTree加载树,普通加载,点一级加载一级

    前端: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <tit ...

  5. 后端工具——Maven——初篇——目录

    目录 Maven的知识体系包括四个部分.Maven的配置文件,Maven命令,Maven生命周期,Maven插件.在介绍Maven之前,首先需要介绍如何安装Maven. 安装:介绍Maven在Linu ...

  6. HTML5学习(6)a元素

    a元素代表超链接 href属性 hyper reference:通常代表跳转地址 target属性:_self在本窗口中打开(默认),_blank在新窗口中打开. id属性:全局属性,表示元素在文档中 ...

  7. arcgis中的Join(合并连接)和Relate(关联连接)

    arcgis中的Join(合并连接)和Relate(关联连接) 一.区别 1.连接关系不一样. Relate(关联连接)方式连接的两个表之间的记录可以是“一对一”.“多对一”.“一对多”的关系 Joi ...

  8. Codeforces Round #618 (Div. 1)A(观察规律)

    实际上函数值为x&(-y) 答案仅和第一个数字放谁有关 #define HAVE_STRUCT_TIMESPEC #include <bits/stdc++.h> using na ...

  9. 每天进步一点点------SOPC PIO (一)

    最近想使用Nios II里的并口PIO口进行双向操作,即需要输出的时候设置为输出方向,需要输入的时候设置为输入方向.在这期间,因为没认真仔细阅读参考文档,走了一点点的弯路.下面就简单的介绍下并行输入/ ...

  10. PHP基础学习笔记3

    一.检索表单信息 PHP 中的 $_GET 和 $_POST 变量用于检索表单中的信息,比如用户输入 提交的表单: <form action="welcome.php" me ...