文章目录

  • 关于本教程
    • 下载源代码
  • 介绍
  • 作者实体
  • AuthorManager:领域服务
  • IAuthorRepository
  • 结论
  • 下一部分

关于本教程

本教程基于版本3.1

在本教程系列中,您将构建一个名为Acme.BookStore的基于ABPWeb应用程序。该应用程序用于管理书籍及其作者的列表。它是使用以下技术开发的:

  • 实体框架核心作为ORM提供者。
  • MVC/Razor页面作为UI框架。

本教程分为以下部分:

第1部分:创建服务器端

第2部分:书籍列表页面

第3部分:创建、更新和删除书籍

第4部分:集成测试

第5部分:授权

第6部分:作者:领域层(此部分)

第7部分:作者:数据库集成

第8部分:作者:应用程序层

第9部分:作者:用户界面

第10部分:书与作者的关系

下载源代码

MVC (Razor Pages) UI with EF Core

介绍

在前面的部分中,我们使用了ABP基础结构轻松构建了一些服务。

  • 使用CrudAppService基类,而不是为标准的创建,读取,更新和删除操作手动开发应用程序服务。

  • 使用通用存储库来完全自动化数据库层。

对于“作者”部分;

  • 我们将手动执行某些操作,以显示在需要时如何执行此操作。

  • 我们将实现一些域驱动设计(DDD)最佳实践

开发将逐层完成,以一次集中在一个单独的层上。在真实的项目中,您将按照前面各部分的功能(垂直)来开发应用程序功能。这样,您将体验两种方法。

作者实体

Acme.BookStore.Domain项目中创建一个Authors文件夹(名称空间),并在其中添加一个Author类:

using System;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;namespace Acme.BookStore.Authors
{public class Author : FullAuditedAggregateRoot<Guid>{public string Name { get; private set; }public DateTime BirthDate { get; set; }public string ShortBio { get; set; }private Author(){/* This constructor is for deserialization / ORM purpose */}internal Author(Guid id,[NotNull] string name,DateTime birthDate,[CanBeNull] string shortBio = null): base(id){SetName(name);BirthDate = birthDate;ShortBio = shortBio;}internal Author ChangeName([NotNull] string name){SetName(name);return this;}private void SetName([NotNull] string name){Name = Check.NotNullOrWhiteSpace(name, nameof(name), maxLength: AuthorConsts.MaxNameLength);}}
}
  • 继承自FullAuditedAggregateRoot<Guid>,可以对实体进行软删除(这意味着在删除它时,它不会在数据库中删除,而只是标记为已删除),并具有所有的审计属性。

  • 对于Name属性的private set限制从此类之外设置此属性。有两种设置名称的方法(在两种情况下,我们都会验证名称):

    • 在构造函数中,同时创建一个新作者。
    • 稍后使用ChangeName方法来更新名称。
  • constructorChangeName方法是internal迫使仅在领域层使用这些方法,使用AuthorManager将在后面说明。

  • Check类是ABP Framework实用程序类,可在检查方法参数时提供帮助(在无效的情况下它会抛出ArgumentException异常)。

AuthorConsts是一个简单的类,位于Acme.BookStore.Domain.Shared项目的Authors名称空间(文件夹)下:

namespace Acme.BookStore.Authors
{public static class AuthorConsts{public const int MaxNameLength = 64;}
}

Acme.BookStore.Domain.Shared项目内部创建了此类,因为稍后我们将在数据传输对象(DTO)上重用该类。

AuthorManager:领域服务

Author构造函数和ChangeName方法是internal的,因此它们只能在领域层中使用。在Acme.BookStore.Domain项目的Authors文件夹(名称空间)中创建一个AuthorManager类:

using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Services;namespace Acme.BookStore.Authors
{public class AuthorManager : DomainService{private readonly IAuthorRepository _authorRepository;public AuthorManager(IAuthorRepository authorRepository){_authorRepository = authorRepository;}public async Task<Author> CreateAsync([NotNull] string name,DateTime birthDate,[CanBeNull] string shortBio = null){Check.NotNullOrWhiteSpace(name, nameof(name));var existingAuthor = await _authorRepository.FindByNameAsync(name);if (existingAuthor != null){throw new AuthorAlreadyExistsException(name);}return new Author(GuidGenerator.Create(),name,birthDate,shortBio);}public async Task ChangeNameAsync([NotNull] Author author,[NotNull] string newName){Check.NotNull(author, nameof(author));Check.NotNullOrWhiteSpace(newName, nameof(newName));var existingAuthor = await _authorRepository.FindByNameAsync(newName);if (existingAuthor != null && existingAuthor.Id != author.Id){throw new AuthorAlreadyExistsException(newName);}author.ChangeName(newName);}}
}
  • AuthorManager强制创建作者并以受控方式更改作者的姓名。应用程序层(稍后将介绍)将使用这些方法。

DDD技巧:除非确实需要领域服务方法并执行一些核心业务规则,否则请不要引入领域服务方法。对于这种情况,我们需要此服务能够强制唯一名称约束。

两种方法都会检查是否存在具有给定名称的作者,并引发在Acme.BookStore.Domain项目(在Authors文件夹中)中定义的特殊业务异常AuthorAlreadyExistsException,如下所示:

using Volo.Abp;namespace Acme.BookStore.Authors
{public class AuthorAlreadyExistsException : BusinessException{public AuthorAlreadyExistsException(string name): base(BookStoreDomainErrorCodes.AuthorAlreadyExists){WithData("name", name);}}
}

BusinessException是一种特殊的异常类型。在需要时抛出与领域相关的异常是一个好习惯。它由ABP框架自动处理,并且可以轻松地进行本地化。WithData(...)方法用于向异常对象提供其他数据,这些数据以后将在本地化消息上使用或用于某些其他目的。

Acme.BookStore.Domain.Shared项目中打开BookStoreDomainErrorCodes并进行如下更改:

namespace Acme.BookStore
{public static class BookStoreDomainErrorCodes{public const string AuthorAlreadyExists = "BookStore:00001";}
}

这是一个唯一的字符串,表示您的应用程序引发的错误代码,并且可以由客户端应用程序处理。对于用户,您可能想对其进行本地化。打开Acme.BookStore.Domain.Shared项目内部的Localization/BookStore/en.json,并添加以下条目:

"BookStore:00001": "There is already an author with the same name: {name}"

然后打开BookStoreDomainSharedModule并在ConfigureServices方法内添加以下代码块:

Configure<AbpExceptionLocalizationOptions>(options =>
{options.MapCodeNamespace("BookStore", typeof(BookStoreResource));
});

每当您抛出AuthorAlreadyExistsException时,最终用户将在UI上看到一条不错的错误消息。

IAuthorRepository

AuthorManager注入IAuthorRepository,因此我们需要对其进行定义。在Acme.BookStore.Domain项目的Authors文件夹(名称空间)中创建此新接口:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;namespace Acme.BookStore.Authors
{public interface IAuthorRepository : IRepository<Author, Guid>{Task<Author> FindByNameAsync(string name);Task<List<Author>> GetListAsync(int skipCount,int maxResultCount,string sorting,string filter = null);}
}
  • IAuthorRepository扩展了标准IRepository<Author, Guid>接口,因此IAuthorRepository也可以使用所有标准存储库方法。

  • FindByNameAsyncAuthorManager中用于按名称查询作者。

  • GetListAsync将在应用程序层中使用,以获取列出的,经过排序和筛选的作者列表,以显示在UI上。

我们将在下一部分中实现此存储库。

这两种方法似乎都没有必要,因为标准存储库已经具有IQueryable并且可以直接使用它们,而不是定义这样的自定义方法。你是对的,就像在一个真实的应用程序中一样。但是,对于本学习教程,解释在真正需要时如何创建自定义存储库方法是很有用的。

结论

这部分涵盖了书店应用程序作者功能的领域层。下图突出显示了在此部分中创建/更新的主要文件:

下一部分

请参阅本教程的下一部分。

Abp vnext Web应用程序开发教程 6 —— 作者:领域层相关推荐

  1. Abp vnext Web应用程序开发教程 9 —— 作者:用户界面

    文章目录 关于本教程 下载源代码 介绍 图书列表页面 Index.cshtml IndexModel.cshtml.cs Index.js 本地化 添加到主菜单 运行应用程序 创建模态 CreateM ...

  2. Abp vnext Web应用程序开发教程 8 —— 作者:应用程序层

    文章目录 关于本教程 下载源代码 介绍 IAuthorAppService AuthorDto GetAuthorListDto CreateAuthorDto UpdateAuthorDto Aut ...

  3. Abp vnext Web应用程序开发教程 7 —— 作者:数据库集成

    文章目录 关于本教程 下载源代码 介绍 数据库上下文 创建一个新的数据库迁移 实现IAuthorRepository 下一部分 关于本教程 本教程基于版本3.1 在本教程系列中,您将构建一个名为Acm ...

  4. Abp vnext Web应用程序开发教程 10 —— 书与作者的关系

    文章目录 关于本教程 下载源代码 介绍 向书实体添加关系 数据库和数据迁移 更新EF核心映射 添加新的EF核心迁移 更改数据播种器 应用层 数据传输对象 IBookAppService BookApp ...

  5. Abp vnext Web应用程序开发教程 4 —— 集成测试

    文章目录 关于本教程 下载源代码 在解决方案中测试项目 添加测试数据 测试BookAppService 下一部分 关于本教程 本教程基于版本3.1 在本教程系列中,您将构建一个名为Acme.BookS ...

  6. Abp vnext Web应用程序开发教程 3 —— 创建、更新和删除书籍

    文章目录 关于本教程 下载源代码 创建新书 创建模态表单 添加"新书"按钮 更新书 EditModal.cshtml.cs 从BookDto映射到CreateUpdateBookD ...

  7. Abp vnext Web应用程序开发教程 1 —— 创建服务器端

    文章目录 关于本教程 下载源代码 创建解决方案 创建书籍实体 BookType枚举 将图书实体添加到DbContext 将图书实体映射到数据库表 添加数据库迁移 添加样本种子数据 更新数据库 创建应用 ...

  8. Abp vnext Web应用程序开发教程 2 —— 图书列表页面

    文章目录 关于本教程 下载源代码 动态JavaScript代理 在开发者控制台中进行测试 本地化 创建书籍页面 将书籍页面添加到主菜单 图书列表 运行最终应用程序 下一部分 关于本教程 本教程基于版本 ...

  9. Abp vnext Web应用程序开发教程 5 —— 授权

    文章目录 关于本教程 下载源代码 权限 权限名称 权限定义 权限管理界面 授权 应用层和HTTP API Razor页面 JavaScript端 菜单项 下一部分 关于本教程 本教程基于版本3.1 在 ...

最新文章

  1. pytorch nn.Conv2d
  2. mqtt服务器性能H3,运用 MQTT-JMeter 插件测试 MQTT 服务器性能
  3. Android TextView 高亮字体并添加点击事件
  4. ExtJs ComboBox 在IE 下 自动完成功能无效的解决方案
  5. 积极打破消极思维模式
  6. 艾创机器人_世界教育机器人大赛 2019赛季世界锦标赛落幕曲靖代表队获多个奖项...
  7. CSS Expression用法总结
  8. 结构型模式概述(Structural Pattern)
  9. 分布式存储中HDFS与Ceph两者的区别是什么,各有什么优势?
  10. 验证列数据是否重复方法归类贴
  11. python建模与仿真控制系统_控制系统的建模与仿真
  12. 多加速器驱动AGX的目标检测与车道分割
  13. 一维的热传导方程向前差分法
  14. WINRAR诊断信息:不可预料的压缩文件末端
  15. 粗糙集(Rough Sets)
  16. python 读取zip包中的数据
  17. 校园网路由器有线中继(针对802.1X)
  18. nextcloud19.0.1部署
  19. STM32F407系统标准库函数之时钟配置 和 位带操作
  20. C语言中的空指针、空指针常量、NULL 0

热门文章

  1. 测速源码_解密,相亲交友直播系统源码,高并发如何做到不卡顿
  2. 中关村企业 大数据_中关村大数据产业联盟秘书长赵国栋:数字经济区别于传统经济 是企业转型升级的顶层战略...
  3. 中国红+金牛|传统农历年新年新春海报稳妥设计方案!
  4. 火热抢购(双11)双12通用海报设计素材,PSD分层!
  5. 最新创意购物促销海报设计,广告人必看!
  6. 电商促销活动那么多,美工需要炫酷海报万能模板!可套用!救急必备!
  7. 建议把英语改成选修的计算机老师,中小学“变动”,英语改为副科?老师没意见家长却愁眉不展...
  8. ansys 内聚力模型_《ANSYS Workbench有限元分析实例详解(静力学)》,9787115446312
  9. 利用ptrace和memfd_create混淆程序名和参数
  10. FD.io VSAP(VPP Stack Acceleration Project),通过FD.io VSAP构建用户态协议栈