16 Star 104 Fork 35

芦荟柚子茶 / SimpleApp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
使用手册.md 10.87 KB
一键复制 编辑 原始数据 按行查看 历史

使用手册

1 如何快速开始

1.1 启动前端

进入项目下的 /web 文件夹,打开命令窗口:

# 第1步:安装依赖
npm install --registry=https://registry.npm.taobao.org
# 第2步:启动项目
npm run serve

启动以后,命令窗口会有如下提示:

  App running at:
  - Local:   http://localhost:81/ 
  - Network: http://192.168.0.105:81/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

打开 http://localhost:81/ 访问前端。

1.2 启动后端

使用 VS2022 打开 /webapi 文件夹下的 SimpleApp.sln

(1)设置启动项目并生成解决方案

Simple.WebApi 设置为启动项目,同时,按 F6 生成解决方案。

(2)修改配置文件

修改 appsettings.json 配置文件里面的数据库连接字符串:

根据自己的具体情况修改 SQL Server 的连接字符串

"ConnectionStrings": {
    "SqlServer": "server=localhost;database=SimpleAppTest;uid=sa;pwd=123456;",
}

(3)数据库迁移

迁移一般分2个步骤:迁移 >> 更新数据库。

1)迁移

运行 /webapi 文件夹下的 migrations.sh 脚本(windows 下运行 migrations.cmd),进行数据库迁移。(迁移后,别急着关闭窗口,需要紧接着进行第2步)

$ ./migrations.sh
执行的迁移版本为: 10
Build started...
Build succeeded.
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 6.0.6 initialized 'SimpleDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer:6.0.6' with options: None
An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy.
Done. To undo this action, use 'ef migrations remove'
迁移完成,请输入数字继续操作
(0/1-无动作,2-更新数据库,3-删除迁移)
请输入:

2)更新数据库

在刚才的命令窗口,按提示更新数据库:

迁移完成,请输入数字继续操作
(0/1-无动作,2-更新数据库,3-删除迁移)
请输入:
2

注意:如果是 windows 环境下直接双击运行该脚本,如果闪退了,说明报错了。

(4)启动项目

VS2022 按 F5 快捷键启动项目。

2 项目结构

├─Simple.Common        # 基础设施
    ├─Components       # 集成组件配置
    ├─Configuration    # 静态配置(相当于appsettings.json的静态帮助类)
    ├─Core             # 非静态功能类
    ├─Extensions       # 扩展方法
    ├─Filters          # 过滤器
    ├─Helpers          # 无状态静态帮助类
    ├─Middlewares      # 中间件
    ├─Models           # 基本数据模型
    ├─Result           # 统一返回结果
    ├─Services         # 基础服务
    └─Startup          # 程序启动配置
├─Simple.Repository    # 仓储层
    ├─Const            # Models 的常量
    ├─Data             # EF Core 的 DbContext
    ├─DataSeed         # 种子数据
    ├─Enum             # Models 的枚举
    ├─Extensions       # 扩展方法
    ├─Migrations       # Code First 迁移文件
    └─Models           # Models 的实体(Entity)
├─Simple.Services      # 服务层
    ├─Cache            # 缓存相关服务
    ├─EventHandlers    # 事件总线订阅者处理程序
    ├─Models           # DTO
    └─Permissions      # 权限控制服务
└─Simple.WebApi        # 表现层
    ├─CustomApp        # 用于配置
    └─Controllers      # 控制器

3 如何进行开发

基本业务开发主要分三步走:创建实体 >> 业务开发 >> 路由配置。

分别在 Repository、Services、WebApi 中编码。

3.1 创建实体

(1)创建实体

在 Repository 层的 /Models 目录下,创建实体,并继承 EntityBaseEntityBase<>BusinessEntityBase<> 等实体。

/// <summary>
/// 角色表
/// </summary>
public class SysRole : EntityBase<Guid>
{
    /// <summary>
    /// 编码
    /// </summary>
    [MaxLength(128)]
    public string Code { get; set; } = "";

    /// <summary>
    /// 名称
    /// </summary>
    [MaxLength(128)]
    public string Name { get; set; } = "";
}

如上代码示例,创建了一个 SysRole 的实体。

(2)数据库迁移

创建实体以后,运行 /webapi 文件夹下的 migrations.sh 脚本,进行数据库迁移。

3.2 业务开发

(1)准备DTO

DTO 为 Data transfer objects 的简写,意为数据传输对象,主要是为了隐藏数据库的数据模型细节,并根据实际项目需要,从表现层读取或返回给表现层的数据对象。

这里准备一个 RoleModel 如下:

public class RoleModel : ModelBase
{
    /// <summary>
    /// 主键
    /// </summary>
    public Guid? Id { get; set; }

    /// <summary>
    /// 编码
    /// </summary>
    [Required(ErrorMessage = "编码是必输的"), MaxLength(128, ErrorMessage = "编码长度不能超过128个字符")]
    public string Code { get; set; }

    /// <summary>
    /// 名称
    /// </summary>
    [Required(ErrorMessage = "名称是必输的"), MaxLength(128, ErrorMessage = "名称长度不能超过128个字符")]
    public string Name { get; set; }

    public override void Configure(Profile profile)
    {
        profile.CreateMap<SysRole, RoleModel>();

        profile.CreateMap<RoleModel, SysRole>()
            .ForMember(d => d.Id, options => options.Ignore());
    }
}

继承 ModelBase 主要是为了重写 Configure 方法,使用 AutoMapper 的能力。

注意:不建议继承 ModelBase,详见实体和模型配置

(2)编写业务服务

在 Services 层中,编写以 Service 结尾的服务类。

如下示例,实现基本的增删改查。

public class RoleService
{
    private readonly SimpleDbContext _context;

    public RoleService(SimpleDbContext context)
    {
        _context = context;
    }

    public async Task<List<RoleModel>> GetAsync()
    {
        var roles = await _context.Set<SysRole>().ToListAsync();
        return MapperHelper.Map<List<RoleModel>>(roles);
    }

    public async Task<int> AddAsync(RoleModel model)
    {
        var role = MapperHelper.Map<SysRole>(model);
        await _context.AddAsync(role);
        return await _context.SaveChangesAsync();
    }

    public async Task<int> UpdateAsync(RoleModel model)
    {
        var role = await _context.Set<SysRole>().Where(r => model.Id == r.Id).FirstOrDefaultAsync();
        MapperHelper.Map<RoleModel, SysRole>(model, role);
        _context.Update(role);
        return await _context.SaveChangesAsync();
    }

    public async Task<int> DeleteAsync(params Guid[] ids)
    {
        var roles = await _context.Set<SysRole>().Where(r => ids.Contains(r.Id)).ToListAsync();
        _context.RemoveRange(roles);
        return await _context.SaveChangesAsync();
    }
}

3.3 路由配置

在 WebApi 中创建控制器并配置

[Route("api/SysRole/[action]")]
[ApiController]
public class RoleController : ControllerBase
{
    private readonly RoleService _roleService;

    public RoleController(RoleService roleService)
    {
        _roleService = roleService;
    }

    [HttpGet]
    public async Task<AppResult> List()
    {
        List<RoleModel> data = await _roleService.GetAsync();
        return AppResult.Status200OK(data: data);
    }

    [HttpPost]
    public async Task<AppResult> Add([FromBody] RoleModel model)
    {
        await _roleService.AddAsync(model);
        return AppResult.Status200OK("新增成功");
    }

    [HttpPost]
    public async Task<AppResult> Edit([FromBody] RoleModel model)
    {
        await _roleService.UpdateAsync(model);
        return AppResult.Status200OK("更新成功");
    }

    [HttpPost]
    public async Task<AppResult> Delete(params Guid[] ids)
    {
        await _roleService.DeleteAsync(ids);
        return AppResult.Status200OK("删除成功");
    }
}

实体和模型配置

由于早期项目追求极简流程,故而将实体配置(或模型配置)加在实体(或模型)中。

这种设计一定程度减少了文件的数量,使得相关的东西更密集,但是在一定程度上会给开发人员造成困扰。

基于单一职责的原则,在升级 8.0 后将实体配置(或模型配置)将实体(或模型)分开。

关于实体配置

这里推荐使用 EF Core 原生的泛型接口 IEntityTypeConfiguration<>SysRole 的配置可以如下:

public class SysRoleConfiguration : IEntityTypeConfiguration<SysRole>
{
    public void Configure(EntityTypeBuilder<SysRole> builder)
    {
        // DataScope 默认值 1
        builder.Property(r => r.DataScope).HasDefaultValue(DataScopeType.All);
    }
}

也可以使用本项目提供的 IEntityConfiguration 接口做配置:

public class SysRoleConfiguration : IEntityConfiguration
{
    public void Configure(ModelBuilder builder)
    {
        // DataScope 默认值 1
        builder.Entity<SysRole>().Property(r => r.DataScope).HasDefaultValue(DataScopeType.All);
    }
}

关于模型配置

模型(Model)的配置,主要是配置 AutoMapper,这里也推荐使用 AutoMapper 原生的配置方式:

public class RoleProfile : Profile
{
    public RoleProfile()
    {
        CreateMap<SysRole, RoleModel>();

        CreateMap<RoleModel, SysRole>()
            .ForMember(d => d.Id, options => options.Ignore());
    }
}

也可以使用本项目提供的 IMapperConfiguration 接口做配置:

public class RoleConfiguration : IMapperConfiguration
{
    public void Configure(Profile profile)
    {
        profile.CreateMap<SysRole, RoleModel>();

        profile.CreateMap<RoleModel, SysRole>()
            .ForMember(d => d.Id, options => options.Ignore());
    }
}

基本能力介绍

1 自动注册实体

所有实体继承抽象类 EntityBase 将会自动注册实体。

2 实体注释不需要 [Comment]

Code First 方式下,如果要给表或字段添加注释,需要使用 [Comment] 标签或 Fulent API 的 HasComment 方法,具体参考:EF Core 文档:创建模型:表注释

在这个项目中,只要实体的类名或属性存在 summary 注释,将会自动将 summary 的内容写入注释,不需要额外使用 [Comment] 配置。不需要任何配置。

注:该功能是基于 XML 的注释文档实现的,必须输出项目的 XML 注释文档才会有效。

3 自动注册服务层服务

所有以 Service 结尾的服务,都会自动注册。

需要在 Program.cs 中配置:

builder.Services.AddAutoServices("Simple.Services");

其中,参数 "Simple.Services" 是服务层程序集名称。

C#
1
https://gitee.com/lisheng741/simpleapp.git
git@gitee.com:lisheng741/simpleapp.git
lisheng741
simpleapp
SimpleApp
master

搜索帮助