基于Generic Repository实现多表自定义CRUD的最优方案与性能咨询
通用Repository扩展方案
核心思路
基于现有通用Repository,通过继承+重写或接口抽象实现自定义业务逻辑,既复用通用CRUD代码,又满足个性化需求,同时保证数据库查询性能。
具体实现方案
1. 优化通用Repository基类
先对现有代码做性能优化,保留通用CRUD能力,同时预留自定义扩展入口:
public abstract class BaseRepository<T> where T : class { private readonly ApplicationContext _context; protected readonly DbSet<T> _entities; private string _errorMessage = string.Empty; public BaseRepository(ApplicationContext context) { _context = context; _entities = context.Set<T>(); } // 优化:返回IQueryable,允许上层拼接查询条件,让数据库执行过滤而非内存加载全表 public virtual IQueryable<T> GetAll() { return _entities; } public virtual T Get(long id) { return _entities.SingleOrDefault(s => s.Id == id); } // 通用插入逻辑,留给子类重写扩展 public virtual void Insert(T entity) { if (entity == null) { throw new ArgumentNullException(nameof(entity)); } _entities.Add(entity); _context.SaveChanges(); } public virtual void Update(T entity) { if (entity == null) { throw new ArgumentNullException(nameof(entity)); } _context.SaveChanges(); } public virtual void Delete(T entity) { if (entity == null) { throw new ArgumentNullException(nameof(entity)); } _entities.Remove(entity); _context.SaveChanges(); } }
2. 为需自定义逻辑的表创建专属Repository
比如需要避免重复插入的用户表,创建子类继承基类并重写对应方法:
public class UserRepository : BaseRepository<User> { public UserRepository(ApplicationContext context) : base(context) { } public override void Insert(User entity) { // 自定义逻辑:数据库层面检查账号是否重复 bool isDuplicate = _entities.Any(u => u.Account == entity.Account); if (isDuplicate) { throw new InvalidOperationException("该账号已存在"); } // 调用基类通用逻辑完成插入 base.Insert(entity); } // 扩展专属查询方法,满足业务需求 public User GetByAccount(string account) { return _entities.SingleOrDefault(u => u.Account == account); } }
3. 无自定义逻辑的表直接复用基类
不需要特殊处理的表(如日志表、配置表),直接注入BaseRepository<XXX>即可,无需额外创建类:
public class LogService { private readonly BaseRepository<Log> _logRepo; public LogService(BaseRepository<Log> logRepo) { _logRepo = logRepo; } public void AddOperationLog(string content) { _logRepo.Insert(new Log { Content = content, CreateTime = DateTime.Now }); } }
性能优化要点
- 基类
GetAll返回IQueryable,让上层业务代码可以拼接Where、OrderBy等条件,最终由数据库执行过滤,避免内存加载全表数据。 - 自定义重复检查逻辑时,使用
_entities.Any()生成SQL查询,而非先查询全表再在内存判断,减少数据传输量。 - 若多个表有相同自定义规则(如软删除、创建时间自动填充),可抽象中间基类(如
SoftDeleteRepository<T>),统一实现逻辑避免重复代码。
适用场景
- 多数表仅需通用CRUD,少数表需个性化逻辑:采用基类+子类重写的方式,兼顾代码复用与业务定制。
- 多表存在相同自定义规则:抽象中间基类,统一实现通用定制逻辑。
- 无特殊业务规则的表:直接使用通用基类,减少冗余代码。
内容的提问来源于stack exchange,提问作者Diego Kabir
相关产品推荐
相关产品推荐

