人生如逆旅, 我亦是行人。|
2022-07-25 15:24阅读: 421评论: 0推荐: 0

ABP框架之CRUD简单示例

最近在学习ABP框架,打算通过一个简单的增删改查示例来快速入门,厘清整个框架的层次逻辑。

1. 前期准备

1.1 创建项目

进入这里下载ABP启动模板:
选择 Multi Page Web Application
img
创建项目
img
解压下载好的压缩包,使用 visual studio2022 (其他版本可能有问题)打开解决方案(即College.sln文件)
img

1.2 使用 MySQL 数据库

ABP 项目初始化后默认使用的是 SQL Server 数据库,要使用 MySQl 数据库需要进行一些配置。

1.2.1 移除并安装相关套件

  1. 在College.EntityFrameworkCore下移除 xxxx.SqlServer
    img
  2. 在College.EntityFrameworkCore下移除 Microsoft.EntityFrameworkCore.Design
    img
  3. 在College.EntityFrameworkCore下安装 Pomelo.EntityFrameworkCore.MySql
    img
  4. 在College.EntityFrameworkCore下安装 Pomelo.EntityFrameworkCore.MySql.Design
    img
  5. 在College.Web.Host下移除 Microsoft.EntityFrameworkCore.Design
    img
  6. 在College.Web.Host下安装 Microsoft.EntityFrameworkCore.Tools
    img

1.2.2 配置 MySQL 数据库的连接

  1. 按下面三张截图修改数据库连接字符串
    img
    img
    img
  2. 修改College.EntityFrameworkCore下的EntityFrameworkCore文件夹下的CollegeDbContextConfigurer.cs
    img

1.2.3 初始化数据库

  1. 删除College.EntityFrameworkCore下的Migrations文件夹
    img
  2. 设置 College.Web.Host 为启动项
    img
  3. 打开程序包管理控制台,选择EntityFrameworkCore
    img
  4. 依次输入下列命令
Add-Migration "AbpZero_Initial"
Update-Database "AbpZero_Initial"

出现下图的信息则意味成功:
img
打开数据库,可以发现数据库已经创建
img

1.2.4 迁移数据库

  1. 设置College.Migrator为启动项
    img
  2. 运行,输入Y,回车
    img
  3. 大功告成
    img

1.3 启动项目

  1. 设置College.Web.Host为启动项目
  2. 运行,出现下图情况则说明配置成功
    img
  3. 测试一下API
    授权,账号为admin,密码是123qwe
    img
    img
    img
    返回状态码200说明请求成功
    img
  4. 设置College.Web.Mvc为启动项目
  5. 运行,出现下图界面说明整个项目都没有问题
    img
  6. 发现样式不对,是因为缺少libs,按照下图操作,再重新启动就好了
    img
  7. 登录,界面显示如下图,到这里准备工作就完成了
    img
    img

2. 领域层创建实体

在领域层(即College.Core)下创建文件夹 Entities, 用于存放实体
在Entities下创建实体类 Course.cs 用于创建课程信息

using Abp.Domain.Entities;
using Abp.Domain.Entities.Auditing;
using Abp.Timing;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Entities
{
    public class Course : Entity<int>, IHasCreationTime
    {
        public Course ()
        {
            this.Code = string.Empty;
            this.DepartmentCode = string.Empty;
            this.Name = string.Empty;
            this.Credits = 0;
            this.Description = string.Empty;
            this.Status = 0;
            this.CreateDate = null;
            this.CreateName = string.Empty;
            this.UpdateDate = null;
            this.UpdateName = string.Empty;
            this.CreationTime = Clock.Now;
        }
        /// <summary>
        /// 课程编号
        /// </summary>
        [StringLength(50)]
        public string Code { get; set; }

        /// <summary>
        /// 院系编号
        /// </summary>
        [StringLength(50)]
        public string DepartmentCode { get; set; }

        /// <summary>
        /// 课程名称
        /// </summary>
        [StringLength (150)]
        public string Name { get; set; }

        /// <summary>
        /// 课程积分
        /// </summary>
        [Range(0, 5)]
        public int Credits { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        [StringLength(200)]
        public string Description { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public  int? Status { get; set; }

        /// <summary>
        /// 创建日期
        /// </summary>
        public DateTime? CreateDate { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [StringLength(50)]
        public string CreateName { get; set; }

        /// <summary>
        /// 修改日期
        /// </summary>
        public DateTime? UpdateDate { get; set; }

        /// <summary>
        /// 修改人
        /// </summary>
        [StringLength(50)]
        public string UpdateName { get; set; }

        public DateTime CreationTime { get; set; }
    }
}

3. 基础设施层更新数据库

在基础设施层(即College.EntityFrameworkCore\EntityFrameworkCore\CollegeDbContext.cs)添加一行 public DbSet<Course> courses { get; set; } // 创建 courses 表

using Microsoft.EntityFrameworkCore;
using Abp.Zero.EntityFrameworkCore;
using College.Authorization.Roles;
using College.Authorization.Users;
using College.MultiTenancy;
using College.Entities;

namespace College.EntityFrameworkCore
{
    public class CollegeDbContext : AbpZeroDbContext<Tenant, Role, User, CollegeDbContext>
    {
        /* Define a DbSet for each entity of the application */
        
        public CollegeDbContext(DbContextOptions<CollegeDbContext> options)
            : base(options)
        {
        }

        public DbSet<Course> courses { get; set; }
    }
}

打开程序包管理工具,项目选择 EntityFrameworkCore,依次执行下列命令

Add-Migration 'AddCourse'
Update-Database -Verbose

看到数据库已经有 course 表则说明创建成功
img
img

4. 应用层创建应用服务

  1. 在应用层(即College.Application)下新建Courses文件夹用来存放Course相关服务
  2. 在Courses文件夹下创建Dto文件夹用来存放数据传输对象
  3. 创建数据传输对象CourseDto、CreateCourseDto和UpdateCourseDto

4.1 创建数据传输对象

CourseDto

using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Courses.Dto
{
    [AutoMapFrom(typeof(Entities.Course))]
    public class CourseDto : EntityDto<int>
    {
        /// <summary>
        /// 课程编号
        /// </summary>
        [StringLength(50)]
        public string Code { get; set; }

        /// <summary>
        /// 院系编号
        /// </summary>
        [StringLength(50)]
        public string DepartmentCode { get; set; }

        /// <summary>
        /// 课程名称
        /// </summary>
        [StringLength(150)]
        public string Name { get; set; }

        /// <summary>
        /// 课程积分
        /// </summary>
        [Range(0, 5)]
        public int Credits { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        [StringLength(200)]
        public string Description { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public int? Status { get; set; }

        /// <summary>
        /// 创建日期
        /// </summary>
        public DateTime? CreateDate { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [StringLength(50)]
        public string CreateName { get; set; }

        /// <summary>
        /// 修改日期
        /// </summary>
        public DateTime? UpdateDate { get; set; }

        /// <summary>
        /// 修改人
        /// </summary>
        [StringLength(50)]
        public string UpdateName { get; set; }

        public DateTime CreationTime { get; set; }
    }
}

CreateCourseDto

using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Courses.Dto
{
    [AutoMapTo(typeof(Entities.Course))]
    public class CreateCourseDto : EntityDto<int>
    {
        /// <summary>
        /// 课程编号
        /// </summary>
        [StringLength(50)]
        public string Code { get; set; }

        /// <summary>
        /// 院系编号
        /// </summary>
        [StringLength(50)]
        public string DepartmentCode { get; set; }

        /// <summary>
        /// 课程名称
        /// </summary>
        [StringLength(150)]
        public string Name { get; set; }

        /// <summary>
        /// 课程积分
        /// </summary>
        [Range(0, 5)]
        public int Credits { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        [StringLength(200)]
        public string Description { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public int? Status { get; set; }

        /// <summary>
        /// 创建日期
        /// </summary>
        public DateTime? CreateDate { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [StringLength(50)]
        public string CreateName { get; set; }

        /// <summary>
        /// 修改日期
        /// </summary>
        public DateTime? UpdateDate { get; set; }

        /// <summary>
        /// 修改人
        /// </summary>
        [StringLength(50)]
        public string UpdateName { get; set; }
    }
}

UpdateCourse

using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Courses.Dto
{
    [AutoMapTo(typeof(Entities.Course))]
    public class UpdateCourse : EntityDto<int>
    {
        /// <summary>
        /// 课程编号
        /// </summary>
        [StringLength(50)]
        public string Code { get; set; }

        /// <summary>
        /// 院系编号
        /// </summary>
        [StringLength(50)]
        public string DepartmentCode { get; set; }

        /// <summary>
        /// 课程名称
        /// </summary>
        [StringLength(150)]
        public string Name { get; set; }

        /// <summary>
        /// 课程积分
        /// </summary>
        [Range(0, 5)]
        public int Credits { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        [StringLength(200)]
        public string Description { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public int? Status { get; set; }

        /// <summary>
        /// 创建日期
        /// </summary>
        public DateTime? CreateDate { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [StringLength(50)]
        public string CreateName { get; set; }

        /// <summary>
        /// 修改日期
        /// </summary>
        public DateTime? UpdateDate { get; set; }

        /// <summary>
        /// 修改人
        /// </summary>
        [StringLength(50)]
        public string UpdateName { get; set; }
    }
}

4.2 创建应用服务接口

在College.Application\Courses下新建接口ICoursAppService.cs

using Abp.Application.Services;
using College.Courses.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Courses
{
    public interface ICourseAppService : IApplicationService
    {


        /// <summary>
        /// 增加
        /// </summary>
        Task<CourseDto> CreateCourse(CreateCourseDto input);

        /// <summary>
        /// 删除
        /// </summary>
        Task<int> DeleteCourse(IEnumerable<int> ids);

        /// <summary>
        /// 更新
        /// </summary>
        Task<CourseDto> UpdateCourse(UpdateCourseDto input);

        /// <summary>
        /// 查询
        /// </summary>
        Task<CourseDto> GetCourseById(int id);
    }
}

4.3 创建应用服务

在College.Application\Courses下新建类CoursAppService.cs

using Abp.Domain.Repositories;
using Abp.ObjectMapping;
using Abp.Timing;
using College.Courses.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Courses
{
    public class CourseAppService : ICourseAppService
    {
        private readonly IRepository<Entities.Course, int> _repository;
        private readonly IObjectMapper _objectmapper;
        public CourseAppService(IRepository<Entities.Course, int> repository, IObjectMapper objectmapper)
        {
            _repository = repository;
            _objectmapper = objectmapper;
        }

        #region 新增

        public Task<CourseDto> CreateCourse(CreateCourseDto input)
        {
            Entities.Course course = _objectmapper.Map<Entities.Course>(input);
            Entities.Course result = _repository.Insert(course);
            CourseDto output = _objectmapper.Map<CourseDto>(result);

            return Task.FromResult(output);
        }

        #endregion

        #region 删除

        public Task<int> DeleteCourse(IEnumerable<int> ids)
        {
            int num = 0;
            foreach(int id in ids)
            {
                _repository.Delete(id);
                ++num;
            }

            return Task.FromResult(num);
        }

        #endregion

        #region 更新

        public Task<CourseDto> UpdateCourse(UpdateCourseDto input)
        {
            Entities.Course course = _objectmapper.Map<Entities.Course>(input);
            course.UpdateDate = Clock.Now;
            Entities.Course result = _repository.Update(course);
            CourseDto output = _objectmapper.Map<CourseDto>(result);

            return Task.FromResult(output);
        }

        #endregion

        #region 查询

        public Task<CourseDto> GetCourseById(int id)
        {
            Entities.Course result = _repository.Get(id);
            CourseDto output = _objectmapper.Map<CourseDto>(result);

            return Task.FromResult(output);
        }

        #endregion
    }
}

4.4 创建映射文件

在College.Application\Courses下新建类CollegeApplicationAutoMapperProfile.cs

using AutoMapper;
using College.Courses.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College
{
    public class CollegeApplicationAutoMapperProfile : Profile
    {
        public CollegeApplicationAutoMapperProfile()
        {
            CreateMap<Entities.Course, CourseDto>();
        }
    }
}

最后展示一下应用层的目录结构
img

5. 展示层创建控制器

在College.Web.Mvc\Controllers下新增类CoursesController.cs

using Abp.AspNetCore.Mvc.Controllers;
using College.Courses;
using College.Courses.Dto;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace College.Web.Controllers
{
    public class CoursesController : AbpController
    {
        private readonly ICourseAppService _courseAppService;

        public CoursesController(ICourseAppService courseAppService)
        {
            _courseAppService = courseAppService;
        }

        [HttpPost]
        public async Task<CourseDto> CreateCourseAsync(CreateCourseDto courseDto)
        {
            return await _courseAppService.CreateCourse(courseDto);
        }

        [HttpDelete]
        public async Task<int> DeleteCourseAsync(IEnumerable<int> ids)
        {
            return await _courseAppService.DeleteCourse(ids);
        }

        [HttpPost]
        public async Task<CourseDto> UpdateCourseAsync(UpdateCourseDto courseDto)
        {
            return await _courseAppService.UpdateCourse(courseDto);
        }

        [HttpPost]
        public async Task<CourseDto> GetCourseAsync(int id)
        {
            return await _courseAppService.GetCourseById(id);
        }
    }
}

6. 验收成果

  1. 检查
    设置College.Web.Host为启动项,运行
    出现下图的结果说明正确
    img
  2. 添加数据
    img
    状态码为200,说明添加数据成功,进入数据库查看一下
    img
    数据库已有数据。
  3. 查询数据
    img
    查询成功,返回数据
    img
  4. 更新数据
    img
  5. 删除数据
    img

7. 改进

如果大家留意的话就会发现,在更新的时候可以把创建人创建时间也更新掉,这显然不是我们想要的。而且更新时间修改人也不需要暴露出来。另外大家应该也注意到一开始我们定义了 Course 这个实体,后面我们又创建了三个数据传输对象Dto,里面的数据类型及个数都是一样的,这不是多次一举吗?
不是的,如果我们在 UpdateCourseDto 中去掉 CreateDateCreateName,刚刚提到的问题就解决了。
Dto 起到不暴露所有数据的作用,同时也可以起到数据验证的作用。
将 UpdateCourseDto.cs 改为:

using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace College.Courses.Dto
{
    [AutoMapTo(typeof(Entities.Course))]
    public class UpdateCourseDto : EntityDto<int>
    {
        /// <summary>
        /// 课程编号
        /// </summary>
        [StringLength(50)]
        public string Code { get; set; }

        /// <summary>
        /// 院系编号
        /// </summary>
        [StringLength(50)]
        public string DepartmentCode { get; set; }

        /// <summary>
        /// 课程名称
        /// </summary>
        [StringLength(150)]
        public string Name { get; set; }

        /// <summary>
        /// 课程积分
        /// </summary>
        [Range(0, 5)]
        public int Credits { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        [StringLength(200)]
        public string Description { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public int? Status { get; set; }


    }
}

再次启动项目查看效果
img
可以发现 CreateNameCreateDateUpdateNameUpdateDate 已经不见了。
其实简单增删改查我们可以不用自己实现,我们只需要提供数据传输对象,再利用框架本身的AsyncCrudAppService即可。这里为了能够更好地厘清框架逻辑才自己实现。

参考

  1. 后端 ABP (ASP.NET Boilerplate) 应用程序开发框架 改用 MySql
  2. ABP入门教程6 - 领域层创建实体
  3. ABP入门教程7 - 基础设施层更新数据库
  4. ABP入门教程8 - 应用层创建应用服务
  5. ABP学习实践(二)--简单的增删改示例
  6. 自定义仓储之增删改查

本文作者:岁月飞扬

本文链接:https://www.cnblogs.com/jerry-1015/p/16516240.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   岁月飞扬  阅读(421)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起