第29课:定义仓储:使用EF Core实现仓储层

学习分享 丨作者 / 郑 子 铭 丨公众号 / DotNet NB / CloudNative NB

首先定义仓储层的接口,以及仓储层实现的基类,抽象类

仓储层的接口

namespace GeekTime.Infrastructure.Core
{
    /// <summary>
    /// 包含普通实体的仓储
    /// 约束 TEntity 必须是继承 Entity 的基类,必须实现聚合根 IAggregateRoot
    /// 也就是说仓储里面存储的对象必须是一个聚合根对象
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public interface IRepository<TEntity> where TEntity : Entity, IAggregateRoot
    {
        IUnitOfWork UnitOfWork { get; }
        TEntity Add(TEntity entity);
        Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default);
        TEntity Update(TEntity entity);
        Task<TEntity> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
        bool Remove(Entity entity);// 由于没有指定主键,只能根据当前实体进行删除操作
        Task<bool> RemoveAsync(Entity entity);
    }

    /// <summary>
    /// 包含指定主键的类型的实体的仓储
    /// 继承了上面的接口 IRepository<TEntity>,也就是说拥有了上面定义的所有方法
    /// 另外一个,它实现了几个跟 Id 相关的操作的方法
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IRepository<TEntity, TKey> : IRepository<TEntity> where TEntity : Entity<TKey>, IAggregateRoot
    {
        bool Delete(TKey id);
        Task<bool> DeleteAsync(TKey id, CancellationToken cancellationToken = default);
        TEntity Get(TKey id);
        Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default);
    }
}

具体抽象类的实现

实现自己的 DbContext

DomainContext

映射关系,针对每一个领域模型创建一个 EntityTypeConfiguration

OrderEntityTypeConfiguration

UserEntityTypeConfiguration

事务处理

要实现对 DomainContext 的事务处理的话,仅仅需要创建一个类 DomainContextTransactionBehavior

为了演示效果,在应用程序启动时,添加一行代码

Startup

数据库的注册部分

ServiceCollectionExtensions

这一行代码的调用位置是在 ConfigureServices 里面

启动程序,运行过程中 EF 框架会根据定义的实体映射关系生成数据库,可在 Mysql 数据库中查看生成结果

接着丰富一下 Order 的映射关系

启动程序,可以看到数据库修改结果

这说明可以在仓储层定义领域模型与数据库的映射关系,这个映射关系可以组织为一个目录,为每一个领域模型设置一个类型来定义,并且这个过程是强类型的,这样的结构,便于后期维护

另外仓储层的话,定义了一个 IOrderRepository,仅仅实现了 IRepository 泛型接口,引进 Order,由于 Order 实际上有一个主键是 long,所以这里把主键类型也传给 IRepository

Order

这样子,Order 的仓储就定义完毕

那么 Order 仓储的实现也非常简单,仅仅需要继承 Repository,把 Order,long,DomainContext 传入泛型 Repository 即可,这里还实现了 IOrderRepository

通过这样简单的继承,可以复用之前定义的代码,快速实现仓储层的定义

可以通过代码提升看到仓储层是有 Add,Update,Remove,Delete 方法,还有 UnitOfWork 的属性

这样一来就完成了仓储层的定义,可以看到仓储层的代码非常的薄,仅仅包含了一些接口的定义和类的继承,需要自定义一些方法的时候,可以在仓储层定义一些特殊方法,比如 AddABC 等特殊的逻辑都可以在这里去实现

另外一个在组织领域模型和数据库的关系的时候,可以很清晰的看到,是在 EntityConfiguration 这个目录下面,为每一个模型定义一个映射类,当领域模型越来越复杂,数据库的结构越来越复杂的时候,这样的组织结构会非常的清晰

GitHub源码链接:

https://github.com/witskeeper/geektime

Last updated