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


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

    更新接口测试:

    删除接口测试:

    项目完成后,如下图所示

  • 相关阅读:

    转:在自己的工具条中使用ArcGIS Engine提供的命令和工具
    配置Subversion Apache TortoiseSVN
    vc++2005移除自定义向导目录
    NetAdvantage2006 For ASP.NET2.0印象
    三天了!今天终于成功安装ArcIMS9.2!
    vss 去除源代码管理
    转:设计模式趣谈
    转一篇:有关项目报告
    演练:使用 Visual Studio Team Test 进行单元测试
  • 原文地址:https://www.cnblogs.com/kasnti/p/12241095.html
Copyright © 2020-2023  润新知