You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:42:44