ABP框架实现通用CRUD领域服务时IRepository为空报错如何解决
错误原因
你抛出的System.ArgumentNullException: Value cannot be null. (Parameter 'source')错误,本质是_genericRepository字段为空,导致调用.Where()的时候触发空参数异常。
你没有给泛型基类GenericManager<T>编写构造函数实现依赖注入,ABP框架没法自动给你注入对应的仓储实例。
修复步骤
1. 给泛型基类补充构造函数注入仓储
修改GenericManager<T>的代码,添加带IRepository<T, int>参数的构造函数,让ABP的DI系统可以自动注入对应实体的仓储:
public class GenericManager<T> : DomainService where T : class, IEntity<int> { public readonly IRepository<T, int> _genericRepository; // 补充构造函数,实现仓储注入 public GenericManager(IRepository<T, int> genericRepository) { _genericRepository = genericRepository; } public async Task<T> GetAsync(int id) => await AsyncExecuter.FirstOrDefaultAsync(_genericRepository.Where(m => m.Id == id)); public async Task AddAsync(T entity) => await _genericRepository.InsertAsync(entity); public async Task AddManyAsync(IEnumerable<T> entities) => await _genericRepository.InsertManyAsync(entities); public async Task UpdateAsync(T entity) => await _genericRepository.UpdateAsync(entity); public async Task UpdateManyAsync(IEnumerable<T> entities) => await _genericRepository.UpdateManyAsync(entities); public async Task DeleteAsync(T entity) => await _genericRepository.DeleteAsync(entity); }
2. 子类继承时调用基类构造函数
修改ClientManager,补充构造函数,把仓储传递给父类:
public class ClientManager : GenericManager<Client> { // 子类构造函数接收仓储,传递给基类 public ClientManager(IRepository<Client, int> repository) : base(repository) { } public async Task<Client> GetClientByNameAsync(string userName) => await AsyncExecuter.FirstOrDefaultAsync(_genericRepository.Where(m => m.UserName == userName)); public async Task<Client> FindClientWithVKID(string vkid) => await AsyncExecuter.FirstOrDefaultAsync(_genericRepository.Where(m => m.VkId == vkid)); }
3. 可选优化(简化代码)
ABP的仓储本身已经封装了GetAsync、InsertAsync等基础CRUD方法,你不需要自己用AsyncExecuter封装,直接调用仓储自带的方法即可,代码可以简化为:
public class GenericManager<T> : DomainService where T : class, IEntity<int> { public readonly IRepository<T, int> _genericRepository; public GenericManager(IRepository<T, int> genericRepository) { _genericRepository = genericRepository; } // 直接调用仓储原生方法即可 public async Task<T> GetAsync(int id) => await _genericRepository.GetAsync(id); public async Task<T> AddAsync(T entity) => await _genericRepository.InsertAsync(entity); public async Task AddManyAsync(IEnumerable<T> entities) => await _genericRepository.InsertManyAsync(entities); public async Task<T> UpdateAsync(T entity) => await _genericRepository.UpdateAsync(entity); public async Task UpdateManyAsync(IEnumerable<T> entities) => await _genericRepository.UpdateManyAsync(entities); public async Task DeleteAsync(T entity) => await _genericRepository.DeleteAsync(entity); }
额外注意点
如果你的Client实体没有默认注册仓储,可以在你的模块类的ConfigureServices方法里开启自动注册所有实体的默认仓储:
Configure<AbpEfCoreOptions>(options => { options.AddDefaultRepositories(includeAllEntities: true); });
内容的提问来源于stack exchange,提问作者Jiggly Dezar
相关产品推荐
相关产品推荐

