ABP 中的仓储
仓储接口
先看 IRepository 仓储接口的定义,位置在 Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs
IRepository
在 ABP 中所有的仓储都是直接或者间接继承自该接口,在 ABP 中仓储接口有两种类别
1interface IRepository<TEntity>2interface IRepository<TEntity, TKey>这两种一种是标明主键类型的,另外一种是未标明主键类型。标注主键类型的接口都会直接或间接继承自未标注主键类型的接口。
IBasicRepository
IBasicRepository 接口继承自 IReadOnlyBasicRepository 定义基本的CURD操作
1interface IReadOnlyBasicRepository<TEntity> : IRepository where TEntity : class, IEntity2interface IReadOnlyBasicRepository<TEntity, TKey> : IRepository where TEntity : where TEntity : class, IEntity<TKey>IEfCoreRepository
下面我们看针对 EF Core 的仓储接口,位置在 Volo.Abp.EntityFrameworkCore\Volo\Abp\Domain\Repositories\EntityFrameworkCore\IEfCoreRepository.cs
1public interface IEfCoreRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity2{3 DbContext DbContext { get; }4 DbSet<TEntity> DbSet { get; }5}6
7public interface IEfCoreRepository<TEntity, TKey> : IEfCoreRepository<TEntity>, IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>8{9}没有做别的东西,定义了数据库上下文。
至此仓储接口也就这些,没有什么可看的。另外一些
IReadOnlyBasicRepository这样的仓储接口最终都被IRepository继承无需多看。
仓储实现
BasicRepositoryBase
BasicRepositoryBase 类完成 IBasicRepositoryBase 接口的抽象实现,比如
1public abstract Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);2public abstract Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);3public abstract Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);4public abstract Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default);5public abstract Task<long> GetCountAsync(CancellationToken cancellationToken = default);6public abstract Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default);BasicRepositoryBase<TEntity> 类拥有的方法操作
1Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)2Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)3Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)4Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)5Task<long> GetCountAsync(CancellationToken cancellationToken = default)6Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)BasicRepositoryBase<TEntity, TKey> 类拥有的方法操作(只列出它自身实现的未列出继承的)
1Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)2Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)3Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)注: 搞笑啊,
BasicRepositoryBase<TEntity, TKey>类竟然没有任何的引用,怎么寻思的。
RepositoryBase
RepositoryBase 依旧是抽象类,完成的都是抽象实现,但他又继承了 BasicRepositoryBase 类,并完成 IRepositoryBase 接口的抽象实现。
RepositoryBase<TEntity> 类拥有的方法操作
1// 暂时未知他们是干什么用的2IDataFilter DataFilter { get; set; }3ICurrentTenant CurrentTenant { get; set; }4IAsyncQueryableExecuter AsyncExecuter { get; set; }5IUnitOfWorkManager UnitOfWorkManager { get; set; }6
7// 这三个没有被引用过8Type ElementType => GetQueryable().ElementType;9Expression Expression => GetQueryable().Expression;10IQueryProvider Provider => GetQueryable().Provider;11
12// 这两个都是直接调用 return GetQueryable();13IQueryable<TEntity> WithDetails()14IQueryable<TEntity> WithDetails(params Expression<Func<TEntity, object>>[] propertySelectors)15
7 collapsed lines
16IQueryable<TEntity> GetQueryable();17
18Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default);19Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)20
21// 应用数据过滤器 干啥用的?22protected virtual TQueryable ApplyDataFilters<TQueryable>(TQueryable query) where TQueryable : IQueryable<TEntity>RepositoryBase<TEntity, TKey> 类拥有的方法操作
1Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)2Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)3Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)EfCoreRepository
EfCoreRepository 是具体实现类,他重写抽象类 RepositoryBase 的所有方法。
先看 EfCoreRepository<TDbContext, TEntity> 类,看它的构造函数
1public EfCoreRepository(IDbContextProvider<TDbContext> dbContextProvider)2{3 _dbContextProvider = dbContextProvider;4 GuidGenerator = SimpleGuidGenerator.Instance;5
6 _entityOptionsLazy = new Lazy<AbpEntityOptions<TEntity>>(7 () => ServiceProvider8 .GetRequiredService<IOptions<AbpEntityOptions>>()9 .Value10 .GetOrNull<TEntity>() ?? AbpEntityOptions<TEntity>.Empty11 );12}都干了什么呢?
-
dbContextProvider通过构造方法注入的方式获取到,用于获得DbContext。IDbContextProvider<TDbContext>的实现类是UnitOfWorkDbContextProvider<TDbContext>它的作用就是通过数据库连接串来创建 EF 的DbContext。
-
GuidGenerator获取一个用于生成 Guid 的工具类对象,实则就是对Guid.NewGuid();的调用。 -
_entityOptionsLazy他做了什么的呢?Lazy延迟加载具体作用看介绍Lazy文章。AbpEntityOptions类是干什么的? 未知。
EfCoreRepository<TDbContext, TEntity, TKey> 类,除了重写父类方法没做其他操作。
我们用的时候一般是从他开始用的,修改的话也是从他开始的,剩下的都是定义的基本的东西,用不到我们去修改操作。