大话领域驱动设计——基础设施层

概述

d7a0bd41e4e2c567a6196e41f120a518.png

基础设施层是整个系统的⽀持层,通过对第三⽅类库的调⽤或系统的抽象和集成来实现对其他层的⽀持。

690ebcf97edcebb88216bbc105475929.png

与传统架构不同在DDD中,数据库访问的具体实现(仓储)也被放在了基础设施层。

addb1408d7fa592f725fffef400e7d8c.png

在DDD的理念中,基础设施层是为领域和用例的逻辑实现提供支撑。在前面的章节我也提到,在DDD的理念中,数据访问具体实现不是设计过程需要关注的重点,所以将具体访问数据库的代码放在了基础设施层。

概览

3ce69d18877f27f1b85e9f4b7c65db70.gif

通常情况下,我们会将提供数据服务连接的相关类和方法存放于一个项目中,而将其他公共类,公共方法存放于另外的一个或多个项目中。这些自定义的公共类库,这里我就不具体讲述,请依据个人项目需要来进行规划设计。

5c1f55c7a590af4f6239e3bcf2ed4981.gif

基础设施层数据库连接服务主要包含以下组件:

仓储(Repository)实现:对领域层定义的仓储接口的实现类,用户封装对领域对象的数据持久化操作的具体实现。

0a0b30c042b59b72544ddbf3ff7e18e9.gif

在ABP框架下,基础设施层提供数据库访问的类库包含应用程序的数据库上下文(DbContext)、数据库映射、仓储的实现等信息。依据项目需要,我们可以通过CLI中的 -d 参数来选择使用EF Core或者MongoDB,分别会包含以下两个类库:

EntityFrameworkCore:是EF Core的基本集成包,支持SQL Server、MySQL、SQLite、Oracle、PostgreSQL数据库。默认使用SQL Server数据库。

MongoDB:以MongoDB为数据库的基础设施层类库。

实现细节

1

默认仓储

d5d8a8f5fb95041e012e980230c9dcf4.gif

ABP提供了用于实体增删改查的默认仓储接口和实现类,在大多数情况下,我们只需要直接注入使用默认仓储 IRepository<TEntity, TKey> 即可,其中TEntity为需要操作的实体,TKey为该实体主键的数据类型。

73217be8dc4eb23aa480497a376e14c8.gif

使用默认仓储时,需要在EntityFrameworkCore项目的Module类中的 ConfigureServices 方法中加入以下代码用于给所有实体创建默认仓储:

context.Services.AddAbpDbContext<MyDbContext>(options =>{options.AddDefaultRepositories(includeAllEntities: true);});

468f1555332b989b80f020e2c11e6c09.png

其中MyDbContext为当前项目的数据上下文,includeAllEntities参数为true时会给所有实体、聚合根创建默认仓储,如果为false则只给聚合根创建默认仓储。

d43773ecefcdbdfd59ace8068357d5f9.gif

在默认仓储中,ABP提供了以下方法可供直接操作数据库:

  • GetAsync:通过lambda 表达式查询单个实体,如果存在多个满足条件的实体,则抛出 InvalidOperationException 异常。

  • FindAsync:通过lambda 表达式查询单个实体,如果存在多个满足条件的实体,则抛出 InvalidOperationException 异常。

  • InsertAsync:添加实体。

  • InsertManyAsync:批量添加。

  • UpdateAsync:更新实体。

  • UpdateManyAsync:批量修改。

  • DeleteAsync:删除实体,也可根据Lambda表达式删除。

  • DeleteManyAsync:批量删除。

  • GetListAsync:获取数据库中所有实体的列表。

  • GetPagedListAsync:分页获取实体集合。

  • GetCountAsync:获取数据库中所有实体的计数。

55f398abe40968c7ca38096b03bfc119.png

GetAsync方法和FindAsync方法的区别为:如果实体未找到,GetAsync抛出 EntityNotFoundException 异常,而FindAsync方法返回 null 

3afa6ea9228e6d54ab9634a83a935c2a.gif

另外,在很多情况下,我们希望获取 IQueryable 类型用于自定义Linq查询,在ABP 5.0版本之后,获取IQueryable方式改为 await _personRepository.GetQueryableAsync(); 

2

自定义仓储

b84d4d15f24c12f29d89394ccddf582b.gif

如果默认仓储不能满足我们的需求,我们可以自定义仓储接口和实现。

b5db7b9c0d4003b040e533b75dc1c37e.gif

自定义仓储接口声明存放与领域层,可继承自 IRepository<TEntity,TKey> ,其实现类存放与基础设施层,继承自 EfCoreRepository<TDbContext,TEntity,TKey> 或 MongoDbRepository<TDbContext, TEntity, TKey> 

3

Dapper集成

9d1db77f0e7838f8c1aadaf8d33f2c6c.gif

在一些情况下,我们希望可以使用自定义的SQL语句进行更灵活的数据库操作或者执行存储过程调用等操作,而Dapper框架可以满足我们需求。

7e39b6a52466d78b7f1b83fe120f7d1c.gif

在ABP,Dapper框架并被没有完整的集成,而是依托于EF Core实现。也就意味着如果要使用Dapper,创建项目时,数据访问对象依旧选择EF Core。

20c559debcb801eb92bd548000d97aea.gif

当使用Dapper时,我们需要创建自定义仓储,并将其实现类继承自 DapperRepository<TDbContext> ,其中TDbContext为EF Core项目的数据上下文。

9da425ce813aff226984e6ae2024784c.gif

具体用法,我们可以参考官方提供的示例:

public class PersonDapperRepository : DapperRepository<MyAppDbContext>, ITransientDependency
{public PersonDapperRepository(IDbContextProvider<MyAppDbContext> dbContextProvider): base(dbContextProvider){}public virtual async Task<List<string>> GetAllPersonNames(){var dbConnection = await GetDbConnectionAsync();return (await dbConnection.QueryAsync<string>("select Name from People", transaction:  await GetDbTransactionAsync())).ToList();}public virtual async Task<int> UpdatePersonNames(string name){var dbConnection = await GetDbConnectionAsync();return await dbConnection.ExecuteAsync("update People set Name = @NewName", new { NewName = name },await GetDbTransactionAsync());}
}

1d86a196f6d5585c3e0f9cce1f151377.png

58f217e2954939965fed4c975001f464.png

8100e0a7191cdd521c31180278b9f85e.png

欢迎加入微信交流群

END

869ed674d771c73650292777ed6eb4d4.png

044be15086f0dd6cd8c8b511f84d70f8.png

关注我获得

更多精彩

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

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

相关文章

【MATLAB统计分析与应用100例】案例004:matlab调用smoothts函数对金融时间序列数据进行平滑处理

时间序列数据进行平滑处理效果预览: Excel原数据部分预览: 1. 读取金融时间序列数据,绘制波形图 x = xlsread(examp03_02.xls); % 从文件examp03_02.xls中读取数据 price = x(:,4)

【MATLAB统计分析与应用100例】案例005:matlab调用medfilt1函数对加噪正弦波信号进行平滑处理

平滑效果预览: 文章目录 1. 产生加噪正弦波信号,绘制加噪波形图2. 调用medfilt1对加噪正弦波信号y进行中值滤波,并绘制波形图1. 产生加噪正弦波信号,绘制加噪波形图 t = linspace(0,2*pi,500); % 产生一个从0到2

十、为影院添加影片及座位安排《仿淘票票系统前后端完全制作(除支付外)》

一、选中添加功能完成 首先打开在线编辑器进入我们的项目&#xff1a;https://editor.ivx.cn/ 在上一节咱们已经完成了对应的准备工作&#xff0c;在这一节中&#xff0c;咱们只需要对其进行调用即可&#xff0c;调用前还需要处理这些数据&#xff1a; 首先选中时&#xff0…

遍历文件夹还原数据库SQL语句

/***** 遍历文件夹进行数据库还原 *******/---需要开启xp_cmdshell 如已经开启 可以略过 /***** Step 1 开启 xp_cmdshell Use Master GO EXEC master.dbo.sp_configure show advanced options, 1 RECONFIGURE WITH OVERRIDE GO EXEC master.dbo.sp_configure xp_cmdshell, 1…

聊聊 C# 和 C++ 中的 泛型模板 底层玩法

最近在看 C 的方法和类模板&#xff0c;我就在想 C# 中也是有这个概念的&#xff0c;不过叫法不一样&#xff0c;人家叫模板&#xff0c;我们叫泛型&#xff0c;哈哈&#xff0c;有点意思&#xff0c;这一篇我们来聊聊它们底层是怎么玩的&#xff1f;一&#xff1a;C 中的模板玩…

Java实现画八卦

八卦是由多个圆叠加而成&#xff0c;如果我们让每个圆都有自己的颜色&#xff0c;那么具体结构便一目了然&#xff0c;如下图所示&#xff1a; 显然只要令对应的圆颜色相同&#xff0c;就能达到我们预期的效果。 用Java就能轻松画出来&#xff1a; import java.awt.BasicStroke…

十一、为影院添加影片制作准备服务《仿淘票票系统前后端完全制作(除支付外)》

一、为影院添加影片的逻辑和思考 首先打开在线编辑器进入我们的项目&#xff1a;https://editor.ivx.cn/ 进入之后找到上一节中制作的页面&#xff0c;咱们设置点击编辑按钮后进入的页面为影院添加影片页&#xff1a; 接着咱们查看影院添加影片页&#xff1a; 在该页中&…

Linux 内核中断内幕【转】

转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/ 本文对中断系统进行了全面的分析与探讨&#xff0c;主要包括中断控制器、中断分类、中断亲和力、中断线程化与 SMP 中的中断迁徙等。首先对中断工作原理进行了简要分析&#xff0c;接着详细探讨了中断亲…

SQL Server表分区

SQL Server表分区 什么是表分区 一般情况下&#xff0c;我们建立数据库表时&#xff0c;表数据都存放在一个文件里。 但是如果是分区表的话&#xff0c;表数据就会按照你指定的规则分放到不同的文件里&#xff0c;把一个大的数据文件拆分为多个小文件&#xff0c;还可以把这…

apt 根据注解,编译时生成代码

apt&#xff1a; Retention后面的值&#xff0c;设置的为CLASS&#xff0c;说明就是编译时动态处理的。一般这类注解会在编译的时候&#xff0c;根据注解标识&#xff0c;动态生成一些类或者生成一些xml都可以&#xff0c;在运行时期&#xff0c;这类注解是没有的~~会依靠动态生…

Hello Playwright:(6)与元素交互

在上一节我们已经了解到如何定位到元素&#xff0c;那么接下来就可以与元素进行交互了。下面的例子都是以百度首页作为测试页面输入文本FillAsync方法用于模拟用户选中元素并输入文本&#xff0c;这会触发元素的 input 事件。该方法只适合<input>、<textarea>等可输…

十二、动态座位响应及用户订票《仿淘票票系统前后端完全制作(除支付外)》

一、动态座位设置及发布 首先打开在线编辑器进入我们的项目&#xff1a;https://editor.ivx.cn/ 上一节中已经完成了座位设置的准备&#xff0c;这一节咱们将完成座位设置及发布的功能。 咱们首先给有座位设置事件&#xff1a; 有座位的事件设置当点击后更改当前的内容为0即…

C# 查询大型数据集

LINQ 语法非常好&#xff0c;但其作用是什么&#xff1f;我们只要查看源数组&#xff0c;就可以看出需要的结果&#xff0c;为什么要查询这种一眼就能看出结果的数据源呢&#xff1f;有时查询的结果不那么明显&#xff0c;在下面的示例中&#xff0c;就创建了一个非常大的数字数…

一、博客首页搭建搭建《iVX低代码仿CSDN个人博客制作》

制作iVX 低代码项目需要进入在线IDE&#xff1a;https://editor.ivx.cn/ 一、头部导航栏思路参考 首先我们可以查看CSDN的博客首页&#xff0c;从中查看一下布局&#xff1a; 在以上首页中&#xff0c;我们可以得知其顶部为一个整行&#xff0c;这个行内容左侧为一个logo&am…

linux samba服务器

本文转自wanglm51051CTO博客&#xff0c;原文链接&#xff1a; http://blog.51cto.com/studyit2016/1890282&#xff0c;如需转载请自行联系原作者

modernizer的意义

modernizer是一个js文件&#xff0c;会检查当前的浏览器支持什么特性&#xff0c;就在Html标签上添加什么类&#xff0c;然后如果不支持添加no-xxx类&#xff0c;这样&#xff0c;就可以针对两种情况写两种css。 http://blog.chinaunix.net/uid-21633169-id-4286857.html转载于…

Rafy 框架 - 幽灵插件(假删除)

Rafy 框架又添新成员&#xff1a;幽灵插件。本文将解释该插件的场景、使用方法、原理。 场景 在开发各类数据库应用系统时&#xff0c;往往需要在删除数据时不是真正地删除数据&#xff0c;而只是把数据标识为‘已删除’状态。这些数据在业务逻辑上是已经完全删除、不可用的数据…

二、博客首页完成《iVX低代码仿CSDN个人博客制作》

制作iVX 低代码项目需要进入在线IDE&#xff1a;https://editor.ivx.cn/ 一、菜单思路参考及制作 在 CSDN 首页中的菜单部分为一串横排的内容&#xff0c;并且可以进行拖动&#xff1a; 首先咱们添加一个行&#xff0c;命名为菜单&#xff1a; 接着肯定是需要设置上下的内边…

现在是2016-09-23,查询2个月后的月份和入职的月份相同的数据

select * from emp where to_char(hiredate,mm)to_char(add_months( sysdate,2),mm); 结果&#xff1a; 转载于:https://www.cnblogs.com/feng666666/p/5900182.html

Git之创建远程分支和删除远程分支

1、创建远程分支browser-1.8.0 在没有创造browser-1.8.0之前,我们先查看下所有分支 git branch -a 可以知道我们目前在browser-1.7.0分支,然后我们创建本地分支browser-1.8.0 git branch browser-1.8.0 再看下所有分支 git branch -a 然后我们再切换到分支browser-1.8.…