ABP实践(3)-ASP.NET Core 2.x版本(从创建实体到输出api)简单实现商品列表及增删改
项目基于前两篇文章.
本章创建一个简单版的商品管理后台api,用到EF Core用code fist迁移数据创建数据库.
创建Goods实体
在领域层xxx.Core项目[新建文件夹Goods;文件夹名称和类名称一样后面引用的时候需要Goods.Goods,所以建议文件夹名称最好是不要与类同名]在文件夹下创建Goods.cs实体类
[Table("goods")] public class Goods : AuditedAggregateRoot<Guid> { /// <summary> /// 商品名称 /// </summary> [Required]//必填 [StringLength(100)]//限制长度100 public string GoodsName { get; set; } /// <summary> /// 价格 /// </summary> public decimal Price { get; set; } /// <summary> /// 描述 /// </summary> public string Describe{ get; set; } /// <summary> /// 剩余数量 /// </summary> public int SurplusQty { get; set; } /// <summary> /// 构造函数 /// </summary> /// <param name="goodsName"></param> /// <param name="price"></param> /// <param name="describe"></param> /// <param name="surplusQty"></param> public Goods(string goodsName, decimal price, string describe,int surplusQty) { GoodsName = goodsName; Price = price; Describe = describe; SurplusQty = surplusQty; } }
ABP有两个基本的实体基类: AggregateRoot(领域驱动设计(DDD)的概念之一)
和 Entity,继承AggregateRoot会默认添加审计属性CreationTime,CreatorId
<Guid>
是Goods
实体的主键类型可以是int,string等根据自己场景设置
将Goods实体添加到DbContext中
在基础层xxx.EntityFrameworkCore下找到xxxDbContext.cs加入Goods实体对应的DbSet
//由于文件夹名称和类文件同名所以需要Goods.Goods不然只需要类名Goods就行了 public DbSet<Goods.Goods> Goods { get; set; }
添加新的Migration并更新数据库
1,打开程序包管理器控制台,默认项目选择Entityframework对应的项目后。执行Add-Migration Add_Goods_Entity
,创建迁移
2,在程序包管理器控制台,输入Update-Database
,回车执行迁移。执行成功后,查看数据库,看是否存在表及初始数据
执行成功之后刷新数据库查看是否有成功创建表goods
3,给goods表添加几条初始化数据
3.1 在基础层xxx.EntityFrameworkCore下创建Goods初始化数据类DefaultGoodsCreator.cs
public class DefaultGoodsCreator { private readonly crazyDbContext _context; private List<crazy.Goods.Goods> GoodsList= GetInitialGoods(); public DefaultGoodsCreator(crazyDbContext context) { _context = context; } private static List<crazy.Goods.Goods> GetInitialGoods() { return new List<crazy.Goods.Goods> { new crazy.Goods.Goods("商品1",100,"描述1",10), new crazy.Goods.Goods("商品2",260,"描述2",50), new crazy.Goods.Goods("商品3",99,"描述2",1), }; } public void Create() { CreateGoods(); } /// <summary> /// 循环添加初始数据 /// </summary> private void CreateGoods() { foreach (var goods in GoodsList) { AddGoodsIfNotExists(goods); } } /// <summary> /// 判断添加不存在的商品数据 /// </summary> /// <param name="goods"></param> private void AddGoodsIfNotExists(crazy.Goods.Goods goods) { if (_context.Goods.IgnoreQueryFilters().Any(l => l.GoodsName == goods.GoodsName)) { return; } _context.Goods.Add(goods); _context.SaveChanges(); } }
3.2在基础层xxx.EntityFrameworkCore找到文件夹Seed下的SeedHelper.cs插入代码
//Goods初始化数据 new DefaultGoodsCreator(context).Create();
设置crazy.Web.Host为启动项运行项目,运行之后数据库就会生成goods初始化数据.
创建应用服务
1在应用服务层xxx.Application创建文件夹Goods>Dto
①添加GoodsDto.cs注意:以下截图中用的是AutoMapFrom(当前实体只能转为映射实体,当前实体必须字段跟映射实体一样)这个是错误的正确的应该是下面代码中的AutoMapTo(当前实体和映射实体可互相转换,只取必要字段不用全部匹配)
[AutoMapTo(typeof(Goods))] public class GoodsDto : AuditedEntityDto<Guid> { /// <summary> /// 商品名称 /// </summary> public string GoodsName { get; set; } /// <summary> /// 价格 /// </summary> public decimal Price { get; set; } /// <summary> /// 描述 /// </summary> public string Describe { get; set; } /// <summary> /// 剩余数量 /// </summary> public int SurplusQty { get; set; } }
[AutoMapTo(typeof(Goods))]
用来创建从Goods
类到GoodsDto
的AutoMapper映射.使用这种方法.你可以将Goods
对象自动转换成GoodsDto
对象
②添加CreateGoodsDto.cs用于在新增接口
using Abp.Application.Services.Dto; using Abp.AutoMapper; using Abp.Runtime.Validation; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text; namespace crazy.Goods.Dto { [AutoMapTo(typeof(Goods))] public class CreateGoodsDto : IShouldNormalize { /// <summary> /// 商品名称 /// </summary> [Required] [StringLength(100)] public string GoodsName { get; set; } /// <summary> /// 价格 /// </summary> public decimal Price { get; set; } /// <summary> /// 描述 /// </summary> public string Describe { get; set; } /// <summary> /// 剩余数量 /// </summary> public int SurplusQty { get; set; } /// <summary> /// 初始化缺省值 /// </summary> public void Normalize() { SurplusQty = 999; Price = 0.01M; } } }
③创建商品查询分页类PagedGoodsResultRequestDto.cs
public class PagedGoodsResultRequestDto: PagedResultRequestDto { public string Keyword { get; set; } }
④在应用服务层的Goods文件夹下创建接口IGoodsAppService.cs
public interface IGoodsAppService : IAsyncCrudAppService< //定义了基础的 CRUD方法:GetAsync, GetListAsync, CreateAsync, UpdateAsync 和 DeleteAsync.如果不需要扩展它,你可以继承空的IApplicationService接口定义你自己的方法 GoodsDto, //展示商品 Guid, //Goods实体的主键 PagedGoodsResultRequestDto, //获取商品的时候用于分页和排序 CreateGoodsDto, //创建 GoodsDto> //更新 { }
⑤在应用服务层的Goods文件夹下创建商品服务类GoodsAppService.cs
public class GoodsAppService : AsyncCrudAppService<Goods, GoodsDto, Guid, PagedGoodsResultRequestDto, CreateGoodsDto, GoodsDto>, IGoodsAppService { public GoodsAppService(IRepository<Goods, Guid> repository)//注入IRepository自动为Goods创建仓储 : base(repository) { } /// <summary> /// 查询接口(使用Keyword查询商品名称) /// </summary> /// <param name="input"></param> /// <returns></returns> protected override IQueryable<Goods> CreateFilteredQuery(PagedGoodsResultRequestDto input) { return Repository.GetAll().WhereIf(!input.Keyword.IsNullOrWhiteSpace(), a => a.GoodsName.Contains(input.Keyword)); } }
到此就可以运行项目得到如下效果