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

概述

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

关注我获得

更多精彩

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值