实现领域驱动设计 - 使用ABP框架 - 更新操作实体
用例演示 - 更新 / 操作实体
一旦一个实体被创建,它将被用例更新/操作,直到它从系统中删除。可以有不同类型的用例直接或间接地更改实体
在本节中,我们将讨论更改 Issue 的多个属性的典型更新操作。
这次,从更新DTO开始:
public class UpdateIssueDto
{
[Required]
public string Title { get; set; }
public string Text { get; set; }
public Guid? AssignedUserId { get; set; }
}
通过与 IssueCreationDto
比较,您看不到 RepositoryId
。因为,我们的系统不允许跨仓库移动问题(想想GitHub仓库)。只有 Title
是必需的,其他属性是可选的
让我们看看 IssueAppService
中的 Update
实现:
public class IssueAppService : ApplicationService, IIssueAppService
{
//省略了依赖注入
public async Task<IssueDto> UpdateAsync(Guid id, UpdateIssueDto input)
{
//从数据库获取问题实体
var issue = await _issueRepository.GetAsync(id);
//修改标题
await _issueManager.ChangeTitleAsync(issue, input.Title);
//修改分配人
if(input.AssignedUserId.HasValue)
{
var user = await _userRepository.GetAsync(input.AssignedUserId.Value);
await _issueManager.AssignToAsync(issue, user);
}
//修改内容 (没有业务规则,接受任何内容)
issue.Text = input.Text;
// 更新实体到数据库
await _issueRepository.UpdateAsync(issue);
//返回表示这个新的问题的DTO
return ObjectMapper.Map<Issue, IssueDto>(issue);
}
}
UpdateAsync
方法把 id 作为一个单独的参数。它不包含在UpdateIssueDto 中。这是一个设计决策,可以帮助ABP将此服务 自动暴露 为 HTTP API 端点路由。所以,这和DDD无关首先从数据库中获取 Issue 实体。
使用
IssueManager
的ChangeTitleAsync
,而不是直接调用Issue.SetTitle(…)
因为我们需要实现重复的Title
检查,就像刚才在实体创建中所做的那样。这需要对 Issue 和 IssueManager 类进行一些更改(将在下面解释)。使用
IssueManager
的AssignToAsync
方法,如果分配的用户在这个请求中被更改直接设置
Issue.Text
,因为没有相关的业务规则。如果以后需要,我们总是可以进行重构将更改保存到数据库。同样,保存实体是协调业务对象和事务的应用程序服务的职责。如果
IssueManager
在ChangeTitleAsync
和AssignToAsync
方法内部保存,将会有双数据库操作 参见讨论:为什么问题不在IssueManager中保存到数据库?最后使用
IObjectMapper
返回一个IssueDto
,该IssueDto
是通过映射从更新的 Issue 实体自动创建的
如前所述,我们需要对 Issue
和 IssueManager
类进行一些更改。
首先,在 Issue 类中设置 SetTitle 为 internal:
internal void SetTitle(string title)
{
Title = Check.NotNullOrWhiteSpace(title, nameof(title));
}
然后在 IssueManager
中添加了一个新方法来更改标题:
public async Task ChangeTitleAsync(Issue issue, string title)
{
if(issue.Title == title)
{
return;
}
//如果存在相同标题的问题,直接抛错
if(await _issueRepository.AnyAsync(i => i.Title == title))
{
throw new BusinessException("IssueTracking:IssueWithSameTitleExists");
}
issue.SetTitle(title);
}
实现领域驱动设计 - 使用ABP框架 - 更新操作实体的更多相关文章
- 实现领域驱动设计 - 使用ABP框架 - 什么是领域驱动设计?
前言: 最近看到ABP官网的一本电子书,感觉写的很好,翻译出来,一起学习下 (Implementing Domain Driven Design) https://abp.io/books DDD简介 ...
- 实现领域驱动设计 - 使用ABP框架 - 通用准则
在进入细节之前,让我们看看一些总体的 DDD 原则 数据库提供者 / ORM 无关性 领域和应用程序层应该与 ORM / 数据库提供程序 无关.它们应该只依赖于 Repository 接口,而 Rep ...
- 实现领域驱动设计 - 使用ABP框架 - 存储库
存储库 Repository 是一个类似于集合的接口,领域层和应用程序层使用它来访问数据持久性系统(数据库),以读写业务对象(通常是聚合) 常见的存储库原则是: 在领域层定义一个存储库接口(因为它被用 ...
- 实现领域驱动设计 - 使用ABP框架 - 解决方案概览
.NET解决方案的分层 下图显示了使用ABP的 应用启动模板 创建的Visual Studio解决方案: 解决方案名称为问题跟踪,它由多个项目组成.通过考虑DDD原则以及开发和部署实践,该解决方案是分 ...
- 实现领域驱动设计 - 使用ABP框架 - 创建实体
用例演示 - 创建实体 本节将演示一些示例用例并讨论可选场景. 创建实体 从实体/聚合根类创建对象是实体生命周期的第一步.聚合/聚合根规则和最佳实践部分建议为Entity类创建一个主构造函数,以保证创 ...
- .net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇
.net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以. ...
- DDD 领域驱动设计-三个问题思考实体和值对象(续)
上一篇:DDD 领域驱动设计-三个问题思考实体和值对象 说实话,整理现在这一篇博文的想法,在上一篇发布出来的时候就有了,但到现在才动起笔来,而且写之前又反复读了上一篇博文的内容及评论,然后去收集资料, ...
- 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇
前言 领域驱动设计,其实已经是一个很古老的概念了,但它的复杂度依旧让学习的人头疼不已. 互联网关于领域驱动的文章有很多,每一篇写的都很好,理解领域驱动设计的人都看的懂. 不过,这些文章对于那些初学者而 ...
- DDD 领域驱动设计-三个问题思考实体和值对象
消息场景:用户 A 发送一个消息给用户 B,用户 B 回复一个消息给用户 A... 现有设计:消息设计为实体并为聚合根,发件人.收件人设计为值对象. 三个问题: 实体最重要的特性是什么? Messag ...
- (转)EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
随机推荐
- Web端IM聊天消息该不该用浏览器本地存储?一文即懂!
本文由转转技术团队刘筱雨分享,原题"一文读懂浏览器本地存储:Web Storage",下文进行了排版和内容优化. 1.引言 鉴于目前浏览器技术的进步(主要是HTML5的普及),在W ...
- Xrm.Internal.openDialog打开对话框自定义页面
在Dynamics CRM平台中使用自定义页面拓展功能实现有多种方式,比如嵌套iframe,比如直接打开一个新页面,再就是打开对话框了,对话框里为自定义页面. 调用方式很简单,先把自定义页面上传好后, ...
- linux网桥(Linux Bridge)的一些个人记录
目录 1. Linux Bridge简述 2. 网桥创建 创建 配置持久化 在Debian/Ubuntu系统上: 在CentOS/RHEL系统上: 启用和验证 3. 关于linux网桥不转发ip帧的问 ...
- w3cschool-Nginx 使用手册
https://www.w3cschool.cn/nginxsysc/ Nginx 使用手册 手册简介 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 ...
- 第三章 (Nginx+Lua)Redis/SSDB安装与使用
目前对于互联网公司不使用Redis的很少,Redis不仅仅可以作为key-value缓存,而且提供了丰富的数据结果如set.list.map等,可以实现很多复杂的功能:但是Redis本身主要用作内存缓 ...
- win11输入法候选区消失
使用win11系统时,中文输入按空格可以,但是出现微软官方输入法没有候选区问题. 解决方法: 首先,打开任务管理器 然后,在进程选项中找到windows输入体验进程,结束该进程(该进程会自动重启). ...
- 基于MPC的快速transformer安全推理框架
论文:一种基于安全多方计算的快速Transformer安全推理方案-刘伟欣 摘要 数据隐私泄露问题:当前Transformer推理应用中用户的数据会被泄露给模型提供方 安全推理方法:基于MPC实现Tr ...
- RockyLinux9编译安装MySQL8
Linux版本: Rocky Linux release 9.5 (Blue Onyx) 1.下载 打开MySQL-Community-Server官方下载页面:https://downloads.m ...
- delphi中实现http请求和提交
在对接本地的一个药械监管系统使用实现的代码,编译环境delphi Xe7 ,使用类TIdHTTP实现网络的get请求和post提交 //设置组件的属性 procedure TfrmMain.SetHt ...
- UNIDAC中TDataSet组件CachedUpdates属性使用
官方方法组合示例,使用UpdatesPending属性可判断是否有修改在缓存区中