Abp 创建一个模版demo并运行

Demo效果 :简单的单表crud后台服务。不包含UI

项目类型是模块ABP。生成的结构和 多应用/单应用 有差异。
结合文档以及git的源码分享一下demo的理解

abp文档:API/Auto API Controllers | Documentation Center | ABP.IO
前置准备:
Net8 环境:下载 .NET 8.0 (Linux、macOS 和 Windows)
Vs2022 17.8版本以上

1.根据指令生成模版

2.项目结构如下

还有个test文件夹我移除了


首先我们要知道各个模块主要干嘛的

领域层
domian :
基本的领域层,它包含前面介绍的所有构建块(实体、值对象、域服务、规范、存储库接口等)
domian.Shared:它包含一些属于领域层的类型,但与所有其他层共享。例如,它可能包含一些与领域对象相关的常量和枚举,但需要被其他层重用

应用层
Application: 
是实现Contracts项目中定义的接口的基本应用程序层 (可以直接将应用层生成接口)
Application.Contracts: 包含应用程序服务接口和这些接口使用的dto。这个项目可以被客户端应用程序共享(包括UI)

基础服务层 
EntityFrameworkCore:它是EF Core的基本集成包。你的应用程序的DbContext,数据库映射,存储库的实现和其他EF Core相关的东西都在这里

表示层 (本次demo没有ui 没这一层)
Web:
 是一个ASP.NET Core MVC / Razor Pages 应用程序, 这是唯一为应用程序和api服务的可执行应用程序

远程服务层
HttpApi:项目包含解决方案定义的HTTP接口。它通常包含MVC控制器和相关模型。因此,您可以在这个项目中编写HTTP接口。
HttpApi.Client:当您有一个需要使用HTTP接口的c#应用程序时,此项目是有用的。一旦客户端应用程序引用了这个项目,它就可以直接注入和使用应用程序服务。这得益于ABP框架的 动态c#客户端API代理系统


1.首先建立实体。 在 Domian 下面新建一个productConfig类 。
继承FullAuditedAggregateRoot 泛型根据你的id的类型。这是abp自带的实体类。但是底层都是必须继承 Entity。这封装包含了基本的修改人和逻辑删除的扩展字段不用单独封了。

2.因为我使用的是ef core 所以刚好在 EntityFrameworkCore 下的 DbContext.cs文件夹下 注入我的表。以及添加数据库的映射关系

3.先在host 下的 appsettings.json里配置好连接字符串 


用的是ef 所以需要数据迁移。首先要准备好确定 dotnet --ef 是否安装。
模版项目在host下执行下面语句(其余项目在EntityFrameworkCore 下执行)
会自动创建个Migrations文件夹

dotnet ef migrations add Added_ProductConfig

然后再执行一下语句生成Abp的基础表 (如果运行项目的时候报错 abpsetting 不存在就是表没创建成功) 。执行完检查下表有米有。

dotnet ef database update


4. 在 Application.Contracts 下创建
1个入参的dto和出参dto

以及1个应用层的接口。

5.在 Domian下新建一个接口 IProductConfigRepository 用于在实体赋值时的验重查询操作

public interface IProductConfigRepository : IRepository<ProductConfig, Guid>
{Task<ProductConfig> FindByNameAsync(string name);Task<List<ProductConfig>> GetListAsync(int skipCount,int maxResultCount,string sorting,string filter = null);
}

EntityFrameworkCore  下创建一个对应的实现

 /// <summary>/// 产品分类表检验类/// </summary>public class EfCoreProductConfigRepository : EfCoreRepository<FinancingInstitutionDbContext, ProductConfig, Guid>,IProductConfigRepository{public EfCoreProductConfigRepository(IDbContextProvider<FinancingInstitutionDbContext> dbContextProvider): base(dbContextProvider){}public async Task<ProductConfig> FindByNameAsync(string name){var dbSet = await GetDbSetAsync();return await dbSet.FirstOrDefaultAsync(p => p.Name == name);}public async Task<List<ProductConfig>> GetListAsync(int skipCount,int maxResultCount,string sorting,string filter = null){var dbSet = await GetDbSetAsync();return await dbSet.WhereIf(!filter.IsNullOrWhiteSpace(),author => author.Name.Contains(filter)).OrderBy(sorting).Skip(skipCount).Take(maxResultCount).ToListAsync();}}

6.在 Domian下面新建一个类  ProductConfigManage 。因为我只有crud。实际对于实体来说有修改操作的只有3个行为。增删改。从面向对象的角度理解会更容易理解。根据行为。做该领域内这个行为需要做的事情。前1个步骤就是为这个做铺垫

 /// <summary>/// 实体层聚合类/// </summary>public class ProductConfigManage : DomainService{private readonly IProductConfigRepository _productConfigRepository;public ProductConfigManage(IProductConfigRepository productConfigRepository){_productConfigRepository = productConfigRepository;}/// <summary>/// 新增/// </summary>/// <returns></returns>public async Task<ProductConfig> CreateAsync([Required] string name, bool status, int sort, Guid partentId){Check.NotNullOrWhiteSpace(name, nameof(name));var checkExits = await _productConfigRepository.FindByNameAsync(name);if (checkExits != null)throw new ProductAlreadyExistsException(name);return new ProductConfig(GuidGenerator.Create(), name, status, sort, partentId);}/// <summary>/// 修改/// </summary>/// <returns></returns>public async Task<ProductConfig> UpdateAsync([Required] ProductConfig config, [Required] string name, bool status, int sort, Guid partentId){Check.NotNullOrWhiteSpace(name, nameof(name));var checkExits = await _productConfigRepository.FindByNameAsync(name);if (checkExits != null && config.Id != checkExits.Id)throw new ProductAlreadyExistsException(name);return config.Upd(name, status, sort, partentId);}/// <summary>/// 删除/// </summary>/// <returns></returns>public async Task<ProductConfig> DeleteAsync([Required] ProductConfig config){var checkExits = await _productConfigRepository.FindAsync(p => p.Id == config.Id);if (checkExits == null)throw new ProductAlreadyExistsException(config.Name);return config.Del();}}

同时实体里。增加对应的增删改 需要的实体赋值 

 /// <summary>/// 基础配置/// </summary>public class ProductConfig : FullAuditedAggregateRoot<Guid>{/// <summary>/// 分类名称/// </summary>public string Name { get; set; } = string.Empty;/// <summary>/// 状态 true 启用 /// </summary>public bool Status { get; set; } = false;/// <summary>/// 排序/// </summary>public int Sort { get; set; } = 0;/// <summary>/// 父级Id/// </summary>public Guid ParentId { get; set; }internal ProductConfig(Guid id, [NotNull] string name, bool status, int sort, Guid parentId){Id = id;SetName(name);Status = status;Sort = sort;ParentId = parentId;}internal ProductConfig Upd([NotNull] string name, bool status, int sort, Guid parentId){SetName(name);Status = status;Sort = sort;ParentId = parentId;return this;}internal ProductConfig Del(){IsDeleted = true;DeletionTime = DateTime.Now;return this;}//效验名称最大为100private void SetName([NotNull] string name){Name = Check.NotNullOrWhiteSpace(name,nameof(name),maxLength: 100);}}

7.完成应用层。在 Application 下面新建 ProductConfigAppService类
继承 ApplicationService。 底层最终都是继承这个。也封装了很多例如 crudappservice 但是必须实现对应的接口。这个就看个人喜好了。这样的写法感觉会比较直观的 行为话。我需要做什么。然后调用指定行为的domian返回实体。然后根据业务需要直接保存。

 /// <summary>/// 产品分类服务/// </summary>public class ProductConfigAppService : ApplicationService, IProductConfigAppService{private readonly IRepository<ProductConfig, Guid> _Repository;private readonly ProductConfigManage _configManager;public ProductConfigAppService(IRepository<ProductConfig, Guid> repository){_Repository = repository;}/// <summary>/// 获取全部配置/// </summary>/// <returns></returns>public async Task<PagedResultDto<ProductConfigDto>> GetAll(){var source = await _Repository.GetListAsync(p => true);if (source == null || source.Count <= 0)return new PagedResultDto<ProductConfigDto>();var returnDto = source.Select(x =>{var dto = ConverMap(x);return dto;}).ToList();var count = await _Repository.GetCountAsync();return new PagedResultDto<ProductConfigDto>(count, returnDto);}/// <summary>/// 获取指定配置/// </summary>/// <returns></returns>public async Task<ProductConfigDto> GetModel(Guid id){var source = await _Repository.FindAsync(p => p.Id.Equals(id));if (source == null)return new ProductConfigDto();return ConverMap(source);}/// <summary>/// 新增配置/// </summary>/// <param name="input"></param>/// <returns></returns>public async Task<ProductConfigDto> CreateAsync(AddAndUpdProductConfigDto input){var model = await _configManager.CreateAsync(input.Name, input.Status, input.Sort, input.ParentId);await _Repository.InsertAsync(model);return ConverMap(model);}/// <summary>/// 修改配置/// </summary>/// <param name="id"></param>/// <param name="input"></param>/// <returns></returns>/// <exception cref="Exception"></exception>public async Task UpdateAsync(AddAndUpdProductConfigDto input){Check.NotDefaultOrNull<Guid>(input.Id, nameof(input.Id));var check = await _Repository.FindAsync(p => p.Id == input.Id);if (check == null)throw new Exception("数据不存在");var model = await _configManager.UpdateAsync(check, input.Name, input.Status, input.Sort, input.ParentId);await _Repository.UpdateAsync(model);}/// <summary>/// 删除配置/// </summary>/// <param name="id"></param>/// <param name="input"></param>/// <returns></returns>/// <exception cref="Exception"></exception>public async Task DeleteAsync([Required] Guid id){Check.NotDefaultOrNull<Guid>(id, nameof(id));var check = await _Repository.FindAsync(p => p.Id == id);if (check == null)throw new Exception("数据不存在");var model = await _configManager.DeleteAsync(check);await _Repository.UpdateAsync(model);}/// <summary>/// 转换实体/// </summary>/// <param name="source"></param>/// <returns></returns>private ProductConfigDto ConverMap(ProductConfig source){return ObjectMapper.Map<ProductConfig, ProductConfigDto>(source);}}

8.应用层写完了。动态生成api启动项目
host下的 FinancingInstitutionHttpApiHostModule 里动态注入我们的模块 生成

9.启动项目

OK 大概流程就是如此
abp是带验签的 。不过只是demo 我没启动authserve项目了。需要使用的话就一样配置authserver服务的连接字符串以及ef的2个指令。按照下面官方文档的运行步骤启动即可

这只是个demo 大概代码写哪里。怎么跑起来。
哈哈哈 万一接口不通啥的很正常因为我还没测。有问题会及时更正文档。
一起学习 一起进步。 欢迎指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/611096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鹅目标检测数据集VOC格式300张

鹅&#xff0c;一种家禽&#xff0c;以其独特的形态、生活习性和文化象征意义而备受人们喜爱。 鹅属于鸟纲、雁形目、鸭科&#xff0c;是一种大型水禽。它们的身体肥胖&#xff0c;羽毛洁白如雪&#xff0c;嘴部扁平且坚硬&#xff0c;脚部有蹼&#xff0c;适合在水中游动。 …

VBA_NZ系列工具NZ11:VBA光标跟随策略

我的教程一共九套及VBA汉英手册一部&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到数据库&#xff0c;到字典&#xff0c;到高级的网抓及类的应用。大家在学习的过程中可能会存在困惑&#xff0c;这么多知识点该如何组织…

【vue3中状态管理工具pinia的使用】pinia状态一(state)

1、安装 yarn add pinia//或者//npm install pinia2、在main.js中引入store // 引入piniaimport { createPinia } from piniaconst pinia createPinia()// 使用piniaapp.use(pinia)3、创建一个Store 在项目根目录的 src文件夹 —— 创建store文件夹 —— 创建 index.js 文件 …

MongoDB查找命令find,让数据返回称心如意

业务系统接入数据库后&#xff0c;每天都有大量的数据写入数据库。面对逐日增加的数据&#xff0c;开发人员或数据分析人员&#xff0c;该如何读取数据&#xff0c;怎样设置条件&#xff0c;从数据库中查询数据&#xff1f; 本文基于mongodb的官方文档&#xff0c;整理出find命…

​电脑技巧:​笔记本电脑电流声的原因和解决方案

目录 一、音频设备接口接触不良 二、笔记本电源问题 三、笔记本电脑驱动程序问题 四、音频硬件问题 五、操作系统内部电磁干扰 六、最后总结 大家在日常生活当中&#xff0c;笔记本电脑已经成为我们工作、学习和娱乐的重要工具。但有时我们在使用过程中可能会遇到一个令人…

机器学习中的隐马尔可夫模型及Python实现示例

隐马尔可夫模型&#xff08;HMM&#xff09;是一种统计模型&#xff0c;用于描述观测序列和隐藏状态序列之间的概率关系。它通常用于生成观测值的底层系统或过程未知或隐藏的情况&#xff0c;因此它被称为“隐马尔可夫模型”。 它用于根据生成数据的潜在隐藏过程来预测未来的观…

移动通信原理与关键技术学习(4)

1.小尺度衰落 Small-Scale Fading 由于收到的信号是由通过不同的多径到达的信号的总和&#xff0c;接收信号的增强有一定的减小。 小尺度衰落的特点&#xff1a; 信号强度在很小的传播距离或时间间隔内的快速变化&#xff1b;不同多径信号多普勒频移引起的随机调频&#xff…

代码随想录算法训练营第15天 | 102. 二叉树的层序遍历 + 226. 翻转二叉树 + 101. 对称二叉树

今日内容 102.层序遍历 226.翻转二叉树 101.对称二叉树 102.二叉树的层序遍历 - Medium 题目链接&#xff1a;力扣-102. 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&…

Matlab 之数据分布拟合

文章目录 Part.I IntroductionPart.II Distribution Fitter APP 的使用Chap.I APP 简介Chap.II 简单使用 Part.III 通过代码实现分布拟合Chap.I 基于 fitdist 函数Chap.II 获取数据的频率分布后进行曲线拟合 Reference Part.I Introduction 本文主要介绍了如何使用 Matlab 对数…

Xcalibur软件Qual Brower程序的使用

找到Qual Brower&#xff1a;在System>Program里 打开采集的数据文件*.RAW&#xff0c;软件界面主窗口能查看色谱图和质谱图&#xff1a; 1、图形的放大和拷贝、色谱中查看峰的质谱信息&#xff1a; 点亮如图图像右上角的按钮&#xff0c;可以激活该图形并进行操作&#x…

JavaScript日期和时间处理手册

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》 ​ ​ ✨ 前言 日期和时间在应用开发中是非常常用的功能。本文将全面介绍JavaScript中处理日期和时间的方…

专业课128分总分400+南京理工大学818信号系统与数字电路南理工考研经验分享

专业课128分总分400南京理工大学818信号系统与数字电路南理工电光院考研经验分享&#xff0c;希望自己的经历对大家有借鉴。 我是在六月底确认自己保不上研然后专心备考的&#xff0c;时间确实比较紧张。虽然之前暑假看了一点高数&#xff0c;但因为抱有保研的期望&#xff0c…

SPI协议介绍

文章目录 一、硬件连线二、引脚含义三、传输示例四、传输模式 一、硬件连线 二、引脚含义 引脚含义DO&#xff08;MOSI - Master Output Slave Input&#xff09;主机发数据&#xff0c;从机收数据DI&#xff08;MISO - Master Input Slave Output&#xff09;主机收数据&…

HarmonyOS4.0系统性深入开发15Want概述

Want概述 Want的定义与用途 Want是对象间信息传递的载体&#xff0c;可以用于应用组件间的信息传递。其使用场景之一是作为startAbility()的参数&#xff0c;包含了指定的启动目标以及启动时需携带的相关数据&#xff0c;如bundleName和abilityName字段分别指明目标Ability所…

金和OA C6 upload_json 任意文件上传漏洞

产品介绍 金和网络是专业信息化服务商,为城市监管部门提供了互联网监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 漏洞概述 金和 OA C6 upload_json接口处存在任意文件上传漏洞&#xff0c;攻击者可以通过构造特殊请求包上…

LTESniffer:一款功能强大的LTE上下行链路安全监控工具

关于LTESniffer LTESniffer是一款功能强大的LTE上下行链路安全监控工具&#xff0c;该工具是一款针对LTE的安全开源工具。 该工具首先可以解码物理下行控制信道&#xff08;PDCCH&#xff09;并获取所有活动用户的下行链路控制信息&#xff08;DCI&#xff09;和无线网络临时…

三分钟教你学会设置PICO不自动休眠

三分钟教你学会设置PICO不自动休眠 大家经常会有这种困扰吧&#xff0c;“诶&#xff0c;我去倒杯水&#xff0c;怎么屏幕就黑了”或者“啊这个活动怎么要在线看这么久&#xff0c;好想去玩手机”之类的。会出现这种问题是因为PICO将自动休眠的时间设置得非常短&#xff0c;大…

Flink-CEP 实战教程

文章目录 1. 基本概念1.1 CEP 是什么1.2 模式&#xff08;Pattern&#xff09;1.3 应用场景 2. 快速上手2.1 引入依赖2.2 入门实例 3. 模式API&#xff08;Pattern API&#xff09;3.1 个体模式3.1.1 基本形式3.1.2 量词&#xff08;Quantifiers &#xff09;3.1.3 条件&#x…

AI Agent落地先行者实在智能:2023人工智能领军者、百强、TOP30揭榜

实在智能连登三榜&#xff01; 【2023年十佳人工智能行业领军人物】 【2023年度人工智能领域创新企业】 【2023年度最具投资价值企业】 喜大普奔&#xff01;近期&#xff0c;国内科技行业颇具含金量的三张榜单接连发布&#xff0c;实在智能皆榜上有名&#xff0c;“2023「…

网络编程套接字(Socket)

文章目录 1 重点知识2 预备知识2.1 理解源IP地址和目的IP地址2.2 认识端口号2.3 理解 "端口号" 和 "进程ID"2.4 理解源端口号和目的端口号2.5 认识TCP协议2.6 认识UDP协议2.7 网络字节序 3 socket编程接口3.1 socket 常见API3.2 sockaddr结构 4 简单的UDP网…