通过一个demo进行开发流程的详细讲解,并且演示如何在满足规范的前提下书写业务,操作DB,使用框架方法以及日志,异常,事务等的处理。
此场景中,我们会创建一个Test_Demo的表,并且包含Id,Name,Number和Email字段,并创建查询,追加,删除,更新等常规操作。
Services
DebtBase
NGP.DebtBase.Api: 债务基础api
App_Data 应用数据文件夹
XmlDocuments dll编译的xml文件用于生成swagger帮助文档
Controllers 控制器文件夹
appsettings.json 应用配置说明参照:[2.3.1](### 2.3.1、appsettings.json)
dockerfile 容器部署文件,相关说明参照:[5.5.2](### 5.5.2)
log4net.config log4net配置文件
Program.cs 程序启动入口
Startup.cs 程序启动类
NGP.DebtBase.Domain 债务基础业务
dll
DebtBaseResource.resx 债务基础相关消息定义
DebtBaseDbInit 债务基础api启动时需要进行的数据库初始化处理
DebtBaseDependencyRegistrar:债务基础业务统一注入类
DebtBaseConst:常量定义
CurrentVersion 当前版本
-
在src/Services/DebtBase/NGP.DebtBase.Api/Controllers 下创建
DemoController.cs
文件 -
在src/Services/DebtBase/NGP.DebtBase.Domain/ 根据以下结构创建文件
Demo : 场景业务单元文件夹
Models :存放相关模型
ApiDto : 存放api请求的
request
和response
对象,分别是:
CreateDemoRequest
QueryDemoRequest
QueryDemoResponse
UpdateDemoRequest
Entities :存放数据库对应的实体对象
Test_Demo
Validation :存放api请求时的验证模型,分别是:
CreateDemoRequestValidator
QueryDemoRequestValidator
UpdateDemoRequestValidator
Maps :存放DB映射和模型映射
DemoModelMapProfile :模型映射文件
Test_DemoMap : 实体映射文件
IDemoService :场景业务接口
DemoService :场景业务实现
-
首先添加DB实体
-
Test_Demo
-
业务表都需要继承
BaseDBEntity
-
其代码如下:
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* Test_Demo Description:
* 测试模型
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-25 [email protected]
*
* ------------------------------------------------------------------------------*/
using NGP.Framework.Core;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// 测试模型
/// </summary>
public class Test_Demo : BaseDBEntity
{
/// <summary>
/// name
/// </summary>
public string Name { get; set; }
/// <summary>
/// number
/// </summary>
public int Number { get; set; }
/// <summary>
/// email
/// </summary>
public string Email { get; set; }
}
}
-
添加DB映射
-
Test_DemoMap :
-
继承
BaseDBEntity
的表映射必须继承BaseDBEntityMap<T>
-
重写
Configure
方法- 其代码如下:
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* Test_DemoMap Description:
* demo实体映射
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using NGP.Framework.Core.Data;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// demo实体映射
/// </summary>
public class Test_DemoMap: BaseDBEntityMap<Test_Demo>
{
/// <summary>
/// 映射配置
/// </summary>
/// <param name="builder"></param>
public override void Configure(EntityTypeBuilder<Test_Demo> builder)
{
builder.ToTable(nameof(Test_Demo));
builder.Property(store => store.Name).HasMaxLength(200).IsRequired();
builder.Property(store => store.Number).IsRequired();
builder.Property(store => store.Email).HasMaxLength(500);
base.Configure(builder);
}
}
}
-
添加api请求和返回模型
-
CreateDemoRequest
-
对象必须继承:
INGPModel
-
代码见下
-
-
QueryDemoRequest 参照:CreateDemoRequest,实现省略
-
UpdateDemoRequest 参照:CreateDemoRequest,实现省略
-
QueryDemoResponse, 实现省略
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* CreateDemoRequest Description:
* 创建demo请求对象
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using NGP.Framework.Core;
using System.Runtime.Serialization;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// 创建demo请求对象
/// </summary>
public class CreateDemoRequest : INGPModel
{
/// <summary>
/// name
/// </summary>
public string Name { get; set; }
/// <summary>
/// number
/// </summary>
public int Number { get; set; }
/// <summary>
/// email
/// </summary>
public string Email { get; set; }
}
}
-
定义验证模型
-
CreateDemoRequestValidator
-
验证对象必须继承
BaseNGPValidator<T>
,此处T
为CreateDemoRequest
-
在构造函数使用
RuleFor
添加对应的规则,代码见下
-
-
QueryDemoRequestValidator
- 实现省略
-
UpdateDemoRequestValidator
-
如果发现验证重复但是属于不同的模型,可采用抽取共同的方法或者继承的方法进行重构
-
实现省略
-
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* CreateDemoRequestValidator Description:
* 创建对象请求验证模型
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using FluentValidation;
using NGP.Framework.Core;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// 创建对象请求验证模型
/// </summary>
public class CreateDemoRequestValidator : BaseNGPValidator<CreateDemoRequest>
{
/// <summary>
/// ctor
/// </summary>
public CreateDemoRequestValidator()
{
RuleFor(x => x.Name)
.NotEmpty()
.WithStatusCode(StatusCode.EmptyError,"名称")
.MaximumLength(20)
.WithStatusCode(StatusCode.MaxLengthError,"名称",20);
RuleFor(x => x.Number)
.NotEmpty()
.WithStatusCode(StatusCode.EmptyError, "数字")
.Must(x => x > 10 && x < 50)
.WithStatusCode(StatusCode.BetweenValueError, "数字", 10,50);
RuleFor(x => x.Email)
.Must(x =>
{
if (string.IsNullOrWhiteSpace(x))
{
return true;
}
return CommonHelper.IsValidEmail(x);
})
.WithStatusCode(StatusCode.FormatError, "邮件", "[email protected]");
}
}
}
-
定义模型映射
-
DemoModelMapProfile
-
必须继承:
Profile
,INGPMapperProfile
-
在构造函数创建模型映射
-
代码如下:
-
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* DemoModelMapProfile Description:
* demo 模型映射
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using AutoMapper;
using NGP.Framework.Core.Infrastructure;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// demo 模型映射
/// </summary>
public class DemoModelMapProfile: Profile, INGPMapperProfile
{
/// <summary>
/// ctor
/// </summary>
public DemoModelMapProfile()
{
CreateMap<Test_Demo, QueryDemoResponse>();
CreateMap<CreateDemoRequest, Test_Demo>();
}
#region Properties
/// <summary>
/// Order of this mapper implementation
/// </summary>
public int Order => 1;
#endregion
}
}
-
定义业务接口
-
IDemoService
-
添加对应的接口方法,
-
如果是分页查询接口,则:
-
请求参数为
NGPPageQueryRequest<T>
,其中T
为当前业务请求对象,此处为QueryDemoRequest
-
返回参数自行定义,可以是模型,也可以是元祖对象
()
-
-
如果是非分页查询接口,则:
- 请求对象为定义的
XxxRequest
对象
- 请求对象为定义的
-
补充注释后代码如下:
-
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* IDemoService Description:
* deme business interface
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using NGP.Framework.Core.Models;
using System.Collections.Generic;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// deme business interface
/// </summary>
public interface IDemoService
{
/// <summary>
/// page query demo data
/// </summary>
/// <param name="request">request info</param>
/// <returns>totalCount data</returns>
(int totalCount, List<QueryDemoResponse> data) Query(NGPPageQueryRequest<QueryDemoRequest> request);
/// <summary>
/// crate demo
/// </summary>
/// <param name="request">request info</param>
/// <returns>create count</returns>
int Create(CreateDemoRequest request);
/// <summary>
/// update demo
/// </summary>
/// <param name="request">update info</param>
/// <returns>update count</returns>
int Update(UpdateDemoRequest request);
/// <summary>
/// delete demo
/// </summary>
/// <param name="request">delete info</param>
/// <returns>delete count</returns>
int Delete(NGPSingleRequest<List<string>> request);
}
}
-
书写api控制器
-
DemoController
-
添加构造函数并注入
IDemoService
-
添加Query,Create,Update,Delete方法
-
代码如下:
-
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* DemoController Description:
* demo控制器
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using Microsoft.AspNetCore.Mvc;
using NGP.DebtBase.Domain.Demo;
using NGP.Framework.Core.Models;
using System.Collections.Generic;
namespace NGP.DebtBase.Api.Controllers
{
/// <summary>
/// demo控制器
/// </summary>
public class DemoController : BaseApiController
{
/// <summary>
/// 服务接口
/// </summary>
private readonly IDemoService _demoService;
/// <summary>
/// ctor
/// </summary>
/// <param name="demoService"></param>
public DemoController(IDemoService demoService)
{
_demoService = demoService;
}
/// <summary>
/// page query demo data
/// </summary>
/// <param name="request">request info</param>
/// <returns>query result data</returns>
[HttpPost("query")]
public ActionResult<NGPDataPageResponse<QueryDemoResponse>> Query(NGPPageQueryRequest<QueryDemoRequest> request)
{
var queryResult = _demoService.Query(request);
return OkPageDataResult(queryResult.totalCount, queryResult.data);
}
/// <summary>
/// crate demo
/// </summary>
/// <param name="request">request info</param>
/// <returns>create result</returns>
[HttpPost("create")]
public ActionResult<NGPDataResponse<int>> Create(CreateDemoRequest request)
{
return OkDataResult(_demoService.Create(request));
}
/// <summary>
/// update demo
/// </summary>
/// <param name="request">update info</param>
/// <returns>update result</returns>
[HttpPost("update")]
public ActionResult<NGPDataResponse<int>> Update(UpdateDemoRequest request)
{
return OkDataResult(_demoService.Update(request));
}
/// <summary>
/// delete demo
/// </summary>
/// <param name="request">delete info</param>
/// <returns>delete result</returns>
[HttpPost("delete")]
public ActionResult<NGPDataResponse<int>> Delete(NGPSingleRequest<List<string>> request)
{
return OkDataResult(_demoService.Delete(request));
}
}
}
-
添加具体业务实现
-
DemoService
-
定义和在构造函数注入需要的接口,本业务会使用:
IUnitRepository
使用EF操作DB的仓储
-
模型的验证都交给对应的
Validator
进行处理,所以方法内不需要进行验证,额外的业务处理请无视此规则 -
使用模型映射时,需要添加
using NGP.Framework.Core;
命名空间,使用.Map<T>
扩展方法
-
-
/* ---------------------------------------------------------------------
* Copyright:
* IXinWu Technology Co., Ltd. All rights reserved.
*
* DemoService Description:
* deme business implementation
*
* Comment Revision Date Author
* ----------------------------- -------- -------- -----------
* Created 1.0 2019-8-27 [email protected]
*
* ------------------------------------------------------------------------------*/
using NGP.Framework.Core;
using NGP.Framework.Core.Models;
using System.Collections.Generic;
using System.Linq;
namespace NGP.DebtBase.Domain.Demo
{
/// <summary>
/// deme business implementation
/// </summary>
public class DemoService : IDemoService
{
/// <summary>
/// ef上下文仓储
/// </summary>
private readonly IUnitRepository _unitRepository;
/// <summary>
/// ctor
/// </summary>
/// <param name="unitRepository"></param>
public DemoService(IUnitRepository unitRepository)
{
_unitRepository = unitRepository;
}
/// <summary>
/// page query demo data
/// </summary>
/// <param name="request">request info</param>
/// <returns>query result data</returns>
public (int totalCount, List<QueryDemoResponse> data) Query(NGPPageQueryRequest<QueryDemoRequest> request)
{
var criteria = new QueryCondition<Test_Demo>(s => s.IsDelete == false &&
s.Name.Contains(request.RequestData.Name));
var query = _unitRepository.All(criteria.Where).Select(s=>s.ToModel< QueryDemoResponse>());
var result = query.ParsePageQuery(request);
return result;
}
/// <summary>
/// crate demo
/// </summary>
/// <param name="request">request info</param>
/// <returns>create result</returns>
public int Create(CreateDemoRequest request)
{
var entity = request.ToEntity<Test_Demo>();
entity.InitAddDefaultFields();
_unitRepository.Insert(entity);
return _unitRepository.SaveChanges();
}
/// <summary>
/// update demo
/// </summary>
/// <param name="request">update info</param>
/// <returns>update result</returns>
public int Update(UpdateDemoRequest request)
{
var entity = _unitRepository.FindById<Test_Demo>(request.Id);
if (entity == null)
{
throw new NGPException(StatusCode.DBNotExistError);
}
entity.InitUpdateDefaultFields();
entity.Name = request.Name;
entity.Email = request.Email;
entity.Number = request.Number;
_unitRepository.Update(entity);
return _unitRepository.SaveChanges();
}
/// <summary>
/// delete demo
/// </summary>
/// <param name="request">delete info</param>
/// <returns>delete result</returns>
public int Delete(NGPSingleRequest<List<string>> request)
{
return _unitRepository.BatchDelete<Test_Demo>(s => request.RequestData.Contains(s.Id));
}
}
}
- 至此一个简单的demo完成,后续持续添加