实现领域驱动设计 - 使用ABP框架 - 解决方案概览
.NET解决方案的分层
下图显示了使用ABP的 应用启动模板 创建的Visual Studio解决方案:
解决方案名称为问题跟踪,它由多个项目组成。通过考虑DDD原则以及开发和部署实践,该解决方案是分层的。下面的小节解释了解决方案中的项目
领域层
领域层分为2个项目
- IssueTracking.Domain 是基本的领域层,它包含前面介绍的所有构建块(实体、值对象、域服务、规范、存储库接口等)
- IssueTracking.Domain.Shared 是一个很单薄的项目,它包含一些属于领域层的类型,但与所有其他层共享。例如,它可能包含一些与领域对象相关的常量和枚举,但需要被其他层重用
应用层
应用层也分为2个项目
- IssueTracking.Application.Contracts 包含应用程序服务接口和这些接口使用的dto。这个项目可以被客户端应用程序共享(包括UI)
- IssueTracking.Application 是实现Contracts项目中定义的接口的基本应用程序层。
表示层
- IssueTracking.Web 是一个ASP.NET Core MVC / Razor Pages 应用程序, 这是唯一为应用程序和api服务的可执行应用程序
远程服务层
- IssueTracking.HttpApi 项目包含解决方案定义的HTTP接口。它通常包含MVC控制器和相关模型。因此,您可以在这个项目中编写HTTP接口。
- IssueTracking.HttpApi.Client 当您有一个需要使用HTTP接口的c#应用程序时,此项目是有用的。一旦客户端应用程序引用了这个项目,它就可以直接注入和使用应用程序服务。这得益于ABP框架的 动态c#客户端API代理系统
友情提示: There is a Console Application in the test folder of the solution,named IssueTracking.HttpApi.Client.ConsoleTestApp. It simply uses the IssueTracking.HttpApi.Client project to consume the APIs exposed by the application. It is just a demo application and you can safely delete it. You can even delete the IssueTracking.HttpApi.Client project if you think that you don't need to them.
基础设施层
在DDD实现中,您可能有一个单一的基础设施项目来实现所有的抽象和集成,或者您可能对每个依赖项有不同的项目
我们建议采取一种平衡的方法;为主要的基础设施依赖项(如 Entity Framework Core)创建单独的项目,为其他基础设施创建一个通用的基础设施项目
ABP的启动解决方案有两个 Entity Framework Core 集成项目
- IssueTracking.EntityFrameworkCore 它是EF Core的基本集成包。你的应用程序的DbContext,数据库映射,存储库的实现和其他EF Core相关的东西都在这里
- IssueTracking.EntityFrameworkCore.DbMigrations 是一个管理Code First数据库迁移的特殊项目。在这个项目中有一个单独的DbContext来跟踪迁移。除了需要创建一个新的数据库迁移或添加一个具有一些数据库表的 应用程序模块 并自然需要创建一个新的数据库迁移外,您通常不会过多地涉及这个项目
你可能想知道为什么 EF Core 会有两个项目。它主要与 模块化 有关。每个模块都有自己独立的DbContext,应用程序也有一个DbContext。DbMigrations项目包含一个模块的联合,用于跟踪和应用单个迁移路径。虽然大多数时候你不需要知道它,但你可以查看 EF Core迁移文档 以获得更多信息
其他项目
还有一个项目,IssueTracking.DbMigrator,这是一个简单的控制台应用程序,它执行迁移数据库和 播种 初始数据。这是一个有用的实用程序应用程序,您可以在开发环境和生产环境中使用它。
解决方案中项目的依赖关系
下图显示了解决方案(IssueTracking)中项目之间的基本依赖关系(项目引用)。IssueTracking部分因为简单没显示)
这些项目之前已经解释过了。现在,我们可以解释依赖关系的原因
- Domain.Shared 是所有其他项目直接或间接依赖的项目。此项目里的所有类型均可被其他项目使用。
- Domain 只依赖 Domain.Shared。因为它已经是领域共享的一部分。例如,Domain.Shared 中的 IssueType 枚举 可以被 Domain 项目中的 Issue 实体使用
- Application.Contracts 依赖 Domain.Shared。通过这种方式,您可以在dto中重用这些共享的类型。比如, 在Domain.Shared中的IssueType 枚举 可以作为 CreateIssueDto 的一个属性
- Application 依赖 Application.Contracts 。因为它实现了应用程序服务接口并使用其中的dto。它还依赖于 Domain,因为应用程序服务被实现为使用在领域层中定义的领域对象
- EntityFrameworkCore 依赖 Domain。因为它将领域对象(实体和值类型)映射到数据库表(因为它是一个ORM),并实现领域中定义的存储库接口
- HttpApi 依赖 Application.Contracts。 因为它里面的 controller 会注入和使用应用服务接口
- HttpApi.Client 依赖 Application.Contracts。因为它可以像前面解释的那样使用应用程序服务
- Web 依赖 HttpApi。因为它提供在其内部定义的HTTP接口。而且,通过这种方式,它间接地依赖于 Application.Contracts 项目, 来使用页面/组件中的应用程序服务
基于DDD的应用程序的执行流程
下图显示了基于DDD模式开发的web应用程序的典型请求流
- 请求通常从UI上的用户交互(用例)开始,该用户交互导致向服务器发出HTTP请求
- 表现层(或分布式服务层)中的MVC控制器或Razor页面处理程序处理请求,并可以在此阶段执行一些横切关注点(授权、验证、异常处理等)。控制器/页面注入相关的应用程序服务接口,并通过发送和接收dto调用其方法
- 应用程序服务使用领域对象(实体、存储库接口、领域服务等)来实现用例。应用层实现一些横切关注点(授权、验证等)。应用程序服务方法应该是一个工作单元。这意味着它应该是原子的。
- 大多数横切关注点都是由ABP框架自动且常规地实现的,通常不需要为它们编写代码
实现领域驱动设计 - 使用ABP框架 - 解决方案概览的更多相关文章
- 实现领域驱动设计 - 使用ABP框架 - 什么是领域驱动设计?
前言: 最近看到ABP官网的一本电子书,感觉写的很好,翻译出来,一起学习下 (Implementing Domain Driven Design) https://abp.io/books DDD简介 ...
- 实现领域驱动设计 - 使用ABP框架 - 通用准则
在进入细节之前,让我们看看一些总体的 DDD 原则 数据库提供者 / ORM 无关性 领域和应用程序层应该与 ORM / 数据库提供程序 无关.它们应该只依赖于 Repository 接口,而 Rep ...
- 实现领域驱动设计 - 使用ABP框架 - 存储库
存储库 Repository 是一个类似于集合的接口,领域层和应用程序层使用它来访问数据持久性系统(数据库),以读写业务对象(通常是聚合) 常见的存储库原则是: 在领域层定义一个存储库接口(因为它被用 ...
- 实现领域驱动设计 - 使用ABP框架 - 创建实体
用例演示 - 创建实体 本节将演示一些示例用例并讨论可选场景. 创建实体 从实体/聚合根类创建对象是实体生命周期的第一步.聚合/聚合根规则和最佳实践部分建议为Entity类创建一个主构造函数,以保证创 ...
- .net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇
.net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以. ...
- 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇
前言 领域驱动设计,其实已经是一个很古老的概念了,但它的复杂度依旧让学习的人头疼不已. 互联网关于领域驱动的文章有很多,每一篇写的都很好,理解领域驱动设计的人都看的懂. 不过,这些文章对于那些初学者而 ...
- 【DDD】使用领域驱动设计思想实现业务系统
最近新接了一个业务系统——社区服务系统,为了快速熟悉和梳理老系统的业务逻辑和代码,同时对老系统代码做一些优化,于是打算花上一个月时间不间断地对老系统服务进行重构.同时,考虑到社区业务的复杂性,想起了之 ...
- 基于ABP落地领域驱动设计-01.全景图
什么是领域驱动设计? 领域驱动设计(简称:DDD)是一种针对复杂需求的软件开发方法.将软件实现与不断发展的模型联系起来,专注于核心领域逻辑,而不是基础设施细节.DDD适用于复杂领域和大规模应用,而不是 ...
- 基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则
目录 前言 聚合 聚合和聚合根原则 包含业务原则 单个单元原则 事务边界原则 可序列化原则 聚合和聚合根最佳实践 只通过ID引用其他聚合 用于 EF Core 和 关系型数据库 保持聚合根足够小 聚合 ...
随机推荐
- Postman+newman+jenkins+git实战
一.接口分类,流程,用例设计 接口分类: 外部接口:被测系统与外部其他系统之间的接口. 承保系统(被测系统),核算系统. 内部接口:被测系统内部各个子模块之间的接口. 承保系统(A模块,B模块) 测试 ...
- IO ——字节流
什么是流? 概念:内存与存储设备之间传输数据的通道.程序运行后保存在内存,文件一般在硬盘中,在程序中读写文件,需要在内存和存储设备中建立通道.数据借助流传输 流的分类: 按流向: 输入流:将存储设备中 ...
- GAIA-IR: GraphScope 上的并行化图查询引擎
在本文中,我们将介绍 GraphScope 图交互式查询引擎 GAIA-IR,它支持高效的 Gremlin 语言表达的交互图查询,同时高度抽象了图上的查询计算,具有高可扩展性. 背景介绍 在海量数据的 ...
- kali 安装 docker
添加密钥 信任 浙大更新源 curl -fsSL http://mirrors.zju.edu.cn/docker-ce/linux/debian/gpg | sudo apt-key add - t ...
- matplotlib画图工具/绘制散点图
绘制散点图 import matplotlib.pyplot as plt fig=plt.figure() ax = fig.add_subplot(111) ax.scatter(x,y, s,c ...
- Django/MySql数据库基本操作&ORM操作
数据库配置: #第一步在settings里面 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbna ...
- Golang 实现 Redis(10): 本地原子性事务
为了支持多个命令的原子性执行 Redis 提供了事务机制. Redis 官方文档中称事务带有以下两个重要的保证: 事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中 ...
- Elasticserach学习笔记(一)
1.什么是Elasticserach? 一个由Java语言开发的全文搜索引擎,全文检索就是根据用户输入查询字符的片段,能查询出包含片段的数据,简单来说就是一个分布式的搜索与分析引擎,它可以完成分布式部 ...
- c# 读取所有磁盘的剩余空间
介绍: 有一个控制台命令是创建指定大小的空文件,因此我想制作一个一键填充剩余磁盘空间的坑人小程序. 想要填充剩余容量,就要先获取所有本地磁盘的剩余空间,这个程序就是用来做这个的. 项目类型为c#控制台 ...
- Html name与id属性的区别
id----id属性规定为 HTML 元素的唯一的标识.当使用html,CSS时,id属性可用作链接锚(link anchor),通过 JavaScript(HTML DOM)getElementBy ...