专栏首页圣杰的专栏ABP入门系列(3)——领域层定义仓储并实现

ABP入门系列(3)——领域层定义仓储并实现

一、先来介绍下仓储

仓储(Repository): 仓储用来操作数据库进行数据存取。仓储接口在领域层定义,而仓储的实现类应该写在基础设施层。

在ABP中,仓储类要实现IRepository接口,接口定义了常用的增删改查以及聚合方法,其中包括同步及异步方法。主要包括以下方法:

ABP针对不同的ORM框架对该接口给予了默认的实现; 针对EntityFramework,提供了EfRepositoryBase<TDbContext, TEntity, TPrimaryKey>的泛型版本的实现方式。 针对NHibernate,提供了NhRepositoryBase<TEntity, TPrimaryKey>的泛型版本的实现方式。

泛型版本的实现就意味着,大多数的时候,这些方法已足已应付一般实体的需要。如果这些方法对于实体来说已足够,我们便不需要再去创建这个实体所需的仓储接口/类。

直接通过在应用服务层定义仓储引用,然后通过构造函数注入即可。在我们的应用服务层即可按以下方式使用Task仓储:

public class TaskAppService : ITaskAppService { 
private readonly IRepository<Task> _taskRepository; 
public TaskAppService(IRepository<Task> taskRepository) 
{ 
    _taskRepository = taskRepository; 
}

示例代码中使用的就是这种方式。

二、如何实现自定义仓储

假设我们需要查找某个用户都分配哪些任务。

  1. 在领域层,创建IRepositories文件夹,然后定义IBackendTaskRepository。
namespace LearningMpaAbp.IRepositories
{
/// <summary>
/// 自定义仓储示例
/// </summary>
public interface IBackendTaskRepository : IRepository<Task>
{
    /// <summary>
    /// 获取某个用户分配了哪些任务
    /// </summary>
    /// <param name="personId">用户Id</param>
    /// <returns>任务列表</returns>
    List<Task> GetTaskByAssignedPersonId(long personId);
}
}

2.在基础架构层,实现该仓储。

namespace LearningMpaAbp.EntityFramework.Repositories
{
public class BackendTaskRepository:LearningMpaAbpRepositoryBase<Task>,IBackendTaskRepository
{
    public BackendTaskRepository(IDbContextProvider<LearningMpaAbpDbContext> dbContextProvider) : base(dbContextProvider)
    {
    }

    /// <summary>
    /// 获取某个用户分配了哪些任务
    /// </summary>
    /// <param name="personId">用户Id</param>
    /// <returns>任务列表</returns>
    public List<Task> GetTaskByAssignedPersonId(long personId)
    {
        var query = GetAll();

        if (personId>0)
        {
            query = query.Where(t => t.AssignedPersonId == personId);
        }

        return query.ToList();
    }
}
}

该仓储实现,继承自模板生成的LearningMpaAbpRepositoryBase泛型抽象类,然后再实现IBackendTaskRepository接口。这里要显示声明实现类的有参构造函数,使用泛型的IDbContextProvider将数据库上下文的子类ChargeStationContext传给父类的构造函数。

三、仓储的注意事项

  1. 仓储方法中,ABP自动进行数据库连接的开启和关闭。
  2. 仓储方法被调用时,数据库连接自动开启且启动事务
  3. 当仓储方法调用另外一个仓储的方法,它们实际上共享的是同一个数据库连接和事务。
  4. 仓储对象都是暂时性的,因为IRepository接口默认继承自ITransientDependency接口。所以,仓储对象只有在需要注入的时候,才会由Ioc容器自动创建新实例。
  5. 默认的泛型仓储能满足我们大部分的需求。只有在不满足的情况下,才创建定制化的仓储。

源码已上传至Github-LearningMpaAbp,可自行参考。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DDD理论学习系列(12)-- 仓储

    1. 引言 DDD中Repository这个单词,主要有两种翻译:资源库和仓储,本文取仓储之译。 说到仓储,我们肯定就想到了仓库,仓库一般用来存放货物,而仓库一...

    圣杰
  • Asp.net mvc 知多少(九)

    本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想...

    圣杰
  • ABP入门系列(13)——Redis缓存用起来

    源码路径:Github-LearningMpaAbp 1. 引言 创建任务时我们需要指定分配给谁,Demo中我们使用一个下拉列表用来显示当前系统的所有用户,以...

    圣杰
  • 安卓7.0在线更新解析包时出现问题

    关于7.0行为变更,FileProvider应用共享文件的问题可以看鸿洋大佬的这篇博客 https://blog.csdn.net/lmj623565791/...

    萬物並作吾以觀復
  • [PHP] PHP服务器接口SAPI中的结构体

    SAPI:在各个服务器抽象层之间遵守着相同的约定,这里我们称之为SAPI接口。例如命令行程序的实现,Apache的mod_php模块实现以及fastcgi的实现...

    陶士涵
  • Python爬虫-百度模拟登录(二)

    参数值都看到了,token、tt、dv、callback这些变化的参数我们都知道了吧,其他的参数固定,别问我为什么。这个logincheck注意到了吗?是不是有...

    星星在线
  • MappedByteBuffer VS FileChannel ,孰强孰弱?

    Java 在 JDK 1.4 引入了 ByteBuffer 等 NIO 相关的类,使得 Java 程序员可以抛弃基于 Stream ,从而使用基于 Block ...

    黄泽杰
  • 重识Activity——生命周期详解

    1. 单个Activity生命周期 *  显示状态——onCreate()、onStart()、onResume() * 隐藏状态——onPause():部...

    城市中的游牧民族
  • LintCode 子数组之和题目分析代码

    给定一个整数数组,找到和为零的子数组。你的代码应该返回满足要求的子数组的起始位置和结束位置

    desperate633
  • 聊聊maxwell的MysqlPositionStore

    maxwell-1.25.1/src/main/java/com/zendesk/maxwell/schema/MysqlPositionStore.java

    codecraft

扫码关注云+社区

领取腾讯云代金券