基于ASP.NET Core 3.1 WebApi搭建後端多層網站架構【8.3-編寫角色業務的增删改】
編寫最簡單的增删改業務,涉及到DI依賴注入的使用、AutoMapper的使用、工作單元與倉儲的使用、雪花Id的生成
2020/01/29, ASP.NET Core 3.1, VS2019
摘要:基于ASP.NET Core 3.1 WebApi搭建後端多層網站架構【8.3-編寫角色業務的增删改】
文章目錄
此分支項目代碼
本章節介紹了編寫最簡單的增删改查業務,涉及到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.cs
、
RoleService.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 });
}
}
}
更新接口測試:
删除接口測試:
項目完成後,如下圖所示