項目基於前兩篇文章.
本章創建一個簡單版的商品管理后台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)); } }
到此就可以運行項目得到如下效果