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. 140. 单词拆分 II

    Q: 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中.返回所有这些可能的句子. 说明: 分隔时可以重复使用字典 ...

  2. try/catch/finally 语句

    定义和用法 try/catch/finally 语句用于处理代码中可能出现的错误信息. 错误可能是语法错误,通常是程序员造成的编码错误或错别字.也 可能是拼写错误或语言中缺少的功能(可能由于浏览器差异 ...

  3. ASP.NET + MVC5 入门完整教程八 -—-- 一个完整的应用程序(上)

    https://blog.csdn.net/qq_21419015/article/details/80509513 SportsStore 1.开始创建Visual Studio 解决方案和项目这里 ...

  4. 数位DP 不要62

    数位DP的问法是从某个数到某个数的区间里,求出满足题目要求的个数: 如本题所说的不要62和4,就是求出这个区间内,满足这一条件的数: 比如问 6 199的这个区间内满足条件的数,那么就求出1到199满 ...

  5. Hadoop中的java基本类型的序列化封装类

    Hadoop将很多Writable类归入org.apache.hadoop.io包中,在这些类中,比较重要的有Java基本类.Text.Writable集合.ObjectWritable等,重点介绍J ...

  6. spring 配置

    在context中配置 如:在base-package指明一个包: <context:component-scan base-package="cn.edu.dao"/> ...

  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>

    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1, ...

  8. Spark编程基础_RDD初级编程

    摘要:Spark编程基础_RDD初级编程 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素 ...

  9. CTF_论剑场 头像

    首先打开链接发现这个链接是一个头像 然后下载这个头像 通过hxd分析一下 在编辑中查找 flag 然后发现flag是一个用base64 加密的一串文字 然后我们将这串文字 解密 然后再通过md5 32 ...

  10. 利用tensorboard将数据可视化

    注:代码是网上下载的,但是找不到原始出处了,侵权则删 先写出visual类: class TF_visualizer(object): def __init__(self, dimension, ve ...