.NET Core开发实战(第26课:工程结构概览:定义应用分层及依赖关系)--学习笔记...

26 | 工程结构概览:定义应用分层及依赖关系

从这一节开始进入微服务实战部分

这一节主要讲解工程的结构和应用的分层

在应用的分层这里定义了四个层次:

1、领域模型层

2、基础设施层

3、应用层

4、共享层

可以通过代码来看一下

源码链接:
https://github.com/witskeeper/geektime/tree/master/microservices

共享层一共建立三个工程:

1、GeekTime.Core:主要承载基础的简单的类型,比如说异常或者一些帮助类

2、GeekTime.Domain.Abstractions:抽象层,领域的抽象是指在领域模型可以定义一些基类或者接口,领域事件接口,领域事件处理接口,还有 Entity 的接口和 Entity 的基类

3、GeekTime.Infrastructure.Core:基础设施的核心层,是指对仓储,还有 EFContext 定义一些共享代码

这些包实际上在不同的项目里面都可以共享,所以建议的做法是把这些代码都通过私有的 NuGet 的仓库来存储,然后其他的工程可以使用 NuGet 包来直接引用即可

领域模型层就是定义领域模型的地方,这里面会有不同的聚合,还有领域事件,不同的聚合下面就是领域模型

基础设施层是仓储层和一些共享代码的实现,这里只定义了仓储层的实现,包括 EF 的 DomainContext,还有 Order 的仓储层,User 的仓储层,还定义了领域模型与数据库之间的映射关系,就是在 EntityConfigurations 这目录下面去定义

应用层分两个,一个工程是 API 层,是用来承载 Web API 或者 Web 应用的,另外一个是后台任务,这个就是用来执行一些特殊的 Job,作为 Job 的宿主运行的,它可以是一个控制台的应用程序

在 Web 层,Web API 层,也分了几个关键目录 Application,Controllers,Extensions,Infrastructure

基础设施层会放一些身份认证缓存之类的与基础设施交互相关的一些代码

扩展层主要是将服务注册进容器的代码和中间件配置的代码,也就是两扩展方法,一个是对 ServiceCollection 的扩展,一个是对 ApplicationBuilder 的扩展

控制器层主要用来定义 Web API,这一层就是定义前后端交互的接口

应用层使用了 CQRS 的设计模式,就是命令与查询职责分离,把命令放在一个目录,把查询放在一个目录,同样的这里还有两个事件处理的目录,一个是领域模型,领域事件的处理,一个是集成事件的处理

再看一下各层之间的依赖关系

Shared 层实际上是不依赖任何层次的,它存储了共享的代码,被各个工程共享

GeekTime.Core,GeekTime.Domain.Abstractions 是不依赖任何工程的,而 GeekTime.Infrastructure.Core 依赖了 GeekTime.Domain.Abstractions,实现了仓储,比如说仓储会依赖 IAggregateRoot 接口

public interface IRepository<TEntity> where TEntity : Entity, IAggregateRoot

领域模型需要继承模型的基类,并且实现一个聚合根的接口,表示它是一个聚合根

public class Order : Entity<long>, IAggregateRoot

领域事件需要实现一个领域事件的接口

public class OrderCreatedDomainEvent : IDomainEvent

基础设施层是一个独立的程序集,实现了仓储的部分,定义了一个 Order 的仓储

public interface IOrderRepository : IRepository<Order, long>

还定义了 Order 仓储的实现

public class OrderRepository : Repository<Order, long, DomainContext>, IOrderRepository
{public OrderRepository(DomainContext context) : base(context){}
}

这里可以看到仓储实际上依赖了基础设施层共享代码里面的仓储的定义 IRepository,这样就可以复用仓储层的代码,这样定义 OrderRepository 就会比较简单,可以复用 Repository 的一些实现

public abstract class Repository<TEntity, TKey, TDbContext> : Repository<TEntity, TDbContext>, IRepository<TEntity, TKey> where TEntity : Entity<TKey>, IAggregateRoot where TDbContext : EFContext
{public Repository(TDbContext context) : base(context){}public virtual bool Delete(TKey id){var entity = DbContext.Find<TEntity>(id);if (entity == null){return false;}DbContext.Remove(entity);return true;}public virtual async Task<bool> DeleteAsync(TKey id, CancellationToken cancellationToken = default){var entity = await DbContext.FindAsync<TEntity>(id, cancellationToken);if (entity == null){return false;}DbContext.Remove(entity);return true;}public virtual TEntity Get(TKey id){return DbContext.Find<TEntity>(id);}public virtual async Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default){return await DbContext.FindAsync<TEntity>(id, cancellationToken);}
}

已经实现了一些基本的方法,增删改查的方法

数据库访问的实现,继承了自己定义的 EFContext,EFContext 作为共享代码在各个工程里面复用

public class DomainContext : EFContext

另外一个比较特殊的是事务处理的对象,这个对象是用来管理整个应用程序的请求上下文中的事务,这样就可以避免手动地去处理事务,简化代码

public class DomainContextTransactionBehavior<TRequest, TResponse> : TransactionBehavior<DomainContext, TRequest, TResponse>
{public DomainContextTransactionBehavior(DomainContext dbContext, ICapPublisher capBus, ILogger<DomainContextTransactionBehavior<TRequest, TResponse>> logger) : base(dbContext, capBus, logger){}
}

应用层依赖了基础设施层,基础设施层又依赖了领域层

应用层实际上是把各层组装在一起的这一层,它是应用程序的一个宿主,协调各层之间的关系,以及组装代码都是在这里实现的

总结一下

领域模型层专注于业务的设计,它不依赖于其他各层,它是相对独立的

基础设施的仓储层仅仅负责领域模型的存取,它不负责任何的业务逻辑代码的承载

推荐使用 CQRS 的模式来设计应用程序,使应用程序的代码结构更加的合理,在团队和项目膨胀的情况下,工程的可维护性不至于急剧的下降

Web API 是面向前端交互的接口,避免依赖领域模型

共享代码建议设计为共享包,使用私有的 NuGet 仓库来分发和管理

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

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

相关文章

mysql outfile 变量_转mysql dumpfile 与 outfile 函数的区别

一直以为两个函数作用是相同的 经过简单测试发现还是有些区别的 如下表admin mysql select * from admin; ------------------------- | uid | name | pass | ------------------------- | 1 | admin | baidusb | | 2 | root | hacksb | | 3 | manage一直以为两个函数作用是相同…

[蓝桥杯][算法提高VIP]排列式-全排列

题目描述 7254是一个不寻常的数&#xff0c;因为它可以表示为7254 39 x 186&#xff0c;这个式子中1~9每个数字正好出现一次 输出所有这样的不同的式子&#xff08;乘数交换被认为是相同的式子&#xff09; 结果小的先输出&#xff1b;结果相同的&#xff0c;较小的乘数较小的…

容器网络是如何影响Kubernetes中数据库性能的?

关于Kubernetes中的数据库&#xff0c;大家最关心的第一个问题是性能。由于这种担心的存在&#xff0c;许多使用Kubernetes进行生产应用程序工作的客户正在Kubernetes之外的裸机或VM上运行数据库。因此&#xff0c;我们致力于深入研究Kubernetes抽象层&#xff0c;确定值得测试…

mysql php状态函数_mysql_stat()查询MySQL服务器当前系统状态

mysql教程&#xff1a;mysql_stat()查询MySQL服务器当前系统状态 定义和用法 mysql_stat() 函数返回 MySQL 服务器的当前系统状态。 如果成功&#xff0c;则该函数返回状态。如果失败&#xff0c;则返回 false。 语法 mysql_stat(connection)参数 描述 connection 可mysql教程&…

聊聊面试的事(应聘方)

这里是Z哥的个人公众号每周五11&#xff1a;45 按时送达当然了&#xff0c;也会时不时加个餐&#xff5e;我的第「134」篇原创敬上原本春节长假之后会有不少人开始新的面试之旅。但是疫情的到来打乱了这个节奏&#xff0c;包括招聘方的计划。因此&#xff0c;在以往是金三银四的…

[信息学奥赛一本通-T1620]质因数分解-数论

题目描述 原题来自&#xff1a;NOIP 2012 普及组 已知正整数 n 是两个不同的质数的乘积&#xff0c;试求出较大的那个质数。 输入 输入只有一行&#xff0c;包含一个正整数 n。 输出 输出只有一行&#xff0c;包含一个正整数 p&#xff0c;即较大的那个质数。 样例输入 21 样…

mysql边备份边导入么_MySQL 怎么导入导出操作

mysql 如何导入导出操作1、MySQL 如何导入导出个别需要数据记录&#xff1f;– 先导出数据所在的表结构&#xff1a;mysql> show create table CHARBASE into outfile “/db/mysql/RS.sql” ;– 将需要单独导出的内容存放在文本文件里&#xff0c;这里一定要注意存放的位置必…

Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(三)

在前面两篇文章中&#xff0c;我介绍了基于IdentityServer4的一个Identity Service的实现&#xff0c;并且实现了一个Weather API和基于Ocelot的API网关&#xff0c;然后实现了通过Ocelot API网关整合Identity Service做身份认证的API请求。今天&#xff0c;我们进入前端开发&a…

[蓝桥杯][算法提高VIP]因式分解

解题思路&#xff1a; 水题&#xff01;&#xff01;&#xff01; 代码如下&#xff1a; #include <iostream> using namespace std; const int N 100010; int p[N]; int k; bool vis[N];void init() {for (int i 2;i<N-1;i){if (!vis[i])p[k] i;for (int j 2*i…

win10 64位操作系统安装mysql_win10,64位操作系统安装mysql-8.0.16经验总结(图文详细,保证一次安装成功)...

机器配置&#xff1a;win10&#xff0c;64位&#xff1b;mysql-8.0.161.mysql下载首先在mysql下载链接下载安装包&#xff1a;点击 Download 按钮进入下载页面&#xff0c;点击下图中的 No thanks, just start my download. 就可立即下载&#xff1a;2.解压及配置文件下载完后&…

基于 Roslyn 实现一个简单的条件解析引擎

基于 Roslyn 实现一个简单的条件解析引擎Intro最近在做一个勋章的服务&#xff0c;我们想定义一些勋章的获取条件&#xff0c;满足条件之后就给用户颁发一个勋章&#xff0c;定义条件的时候会定义需要哪些参数&#xff0c;参数的类型&#xff0c;获取勋章的时候会提供所需要的参…

[蓝桥杯][算法提高VIP]断案-枚举

题目描述 公安人员审问甲、乙、丙、丁四个嫌疑犯&#xff0c;已确知&#xff0c;这四个人当中仅有一人是偷窃者&#xff0c;还知道这四个人的答话&#xff0c;要么完全诚实&#xff0c;要么完全说谎。在回答公安人员的问话中&#xff1a; 甲说&#xff1a;“乙没有偷&#xff0…

BeetleX之vue-autoui自匹配UI插件

vue-autoui 是一款基于vue和element扩展的一个自动化UI控件&#xff0c;它主要提供两个控件封装分别是auto-form和auto-grid; 通过这两个控件可以完成大多数的信息输入和查询输出的需要.auto-form和auto-grid是通过json来描述展示的结构&#xff0c;在处理上要比写html标签来得…

[蓝桥杯][算法提高VIP]最小乘积(提高型)-排序

题目描述 给两组数&#xff0c;各n个。 请调整每组数的排列顺序&#xff0c;使得两组数据相同下标元素对应相乘&#xff0c;然后相加的和最小。要求程序输出这个最小值。 例如两组数分别为:1 3 -5和-2 4 1 那么对应乘积取和的最小值应为&#xff1a; (-5) * 4 3 * (-2) 1 * …

protobufjs 命令执行_protobufjs简单使用

npm i protobufjs -D添加两个proto文件User.protosyntax "proto3";package login;message PBUser {string uid 1;string pwd 2;int64 age 3;}Login.protosyntax "proto3";package login;import "./User.proto";message LoginReq {PBUser us…

.NET Core开发实战(第27课:定义Entity:区分领域模型的内在逻辑和外在行为)--学习笔记...

27 | 定义Entity&#xff1a;区分领域模型的内在逻辑和外在行为上一节讲到领域模型分为两层一层是抽象层&#xff0c;定义了公共的接口和类另一层就是领域模型的定义层先看一下抽象层的定义1、实体接口 IEntitynamespace GeekTime.Domain {public interface IEntity{object[] G…

洛谷 P1596 [USACO10OCT]Lake Counting S-dfs

题目描述 Due to recent rains, water has pooled in various places in Farmer John’s field, which is represented by a rectangle of N x M (1 < N < 100; 1 < M < 100) squares. Each square contains either water (‘W’) or dry land (’.’). Farmer Jo…

国籍 mysql_国籍表SQL,按首字母升序排序

-- phpMyAdmin SQL Dump-- version phpStudy 2014---- 主机: localhost-- 生成日期: 2015 年 12 月 16 日 14:45-- 服务器版本: 5.5.40-- PHP 版本: 5.3.29SET SQL_MODE"NO_AUTO_VALUE_ON_ZERO";SET time_zone "00:00";;;;;---- 数据库: test---- -------…

Abp vNext发布v2.3!

在全球范围内病毒笼罩的日子里,我们发布了ABP框架v2.3, 这篇文章将说明本次发布新增内容和过去的两周我们做了什么.关于新冠病毒和我们的团队关于冠状病毒的状况我们很难过.在Volosoft的团队,我们有不同国家的远程工作者在自己家里工作.从上周开始,我们已经完全开始在家远程工作…

python可以生成ios应用嘛_用python编写ios应用

自从发现了kivy这个东西,就动了用pyhon写ios程序的念头,因为python确实好写,而且我只会这个,懒得去学object-C..不过具体开始搭环境却折腾了好久,我都快放弃了,不过最后还是搭了出来,分享一些心得吧. 1.首先是mac osx环境,这个用虚拟机就行,网上教程很多 2.接下来就是安装Xcode…