进入项目下的 /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/ 访问前端。
使用 VS2022 打开 /webapi
文件夹下的 SimpleApp.sln
将 Simple.WebApi
设置为启动项目,同时,按 F6 生成解决方案。
修改 appsettings.json
配置文件里面的数据库连接字符串:
根据自己的具体情况修改 SQL Server 的连接字符串
"ConnectionStrings": {
"SqlServer": "server=localhost;database=SimpleAppTest;uid=sa;pwd=123456;",
}
迁移一般分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 环境下直接双击运行该脚本,如果闪退了,说明报错了。
VS2022 按 F5 快捷键启动项目。
├─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 # 控制器
基本业务开发主要分三步走:创建实体 >> 业务开发 >> 路由配置。
分别在 Repository、Services、WebApi 中编码。
在 Repository 层的 /Models
目录下,创建实体,并继承 EntityBase
或 EntityBase<>
或 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
的实体。
创建实体以后,运行 /webapi
文件夹下的 migrations.sh
脚本,进行数据库迁移。
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,详见实体和模型配置。
在 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();
}
}
在 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());
}
}
所有实体继承抽象类 EntityBase
将会自动注册实体。
[Comment]
Code First 方式下,如果要给表或字段添加注释,需要使用 [Comment]
标签或 Fulent API 的 HasComment
方法,具体参考:EF Core 文档:创建模型:表注释。
在这个项目中,只要实体的类名或属性存在 summary 注释,将会自动将 summary 的内容写入注释,不需要额外使用 [Comment]
配置。不需要任何配置。
注:该功能是基于 XML 的注释文档实现的,必须输出项目的 XML 注释文档才会有效。
所有以 Service
结尾的服务,都会自动注册。
需要在 Program.cs
中配置:
builder.Services.AddAutoServices("Simple.Services");
其中,参数 "Simple.Services"
是服务层程序集名称。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。