你是否还在为每个实体类都要写一套增删改查代码而烦恼?是否厌倦了在不同Service层看到几乎相同的数据操作逻辑?

如果你正面临这些痛点,那么今天这篇文章将彻底改变你的编程思维! 我将手把手教你构建一个基于SqlSugar的泛型仓储模式,让你的数据访问层从此告别重复,拥抱优雅。

🎯 什么是泛型仓储模式?为什么它如此重要?

传统方式的痛点分析

在没有使用仓储模式之前,我们的代码通常是这样的:

public class UserService
{
    public async Task<List<User>> GetUsersAsync()
    {
        // 重复的数据库操作代码
        using var db = new SqlSugar.SqlSugarClient(config);
        return await db.Queryable<User>().ToListAsync();
    }

    public async Task<bool> AddUserAsync(User user)
    {
        // 又是重复的代码...
        using var db = new SqlSugar.SqlSugarClient(config);
        return await db.Insertable(user).ExecuteCommandAsync() > 0;
    }
}

publicclass ProductService
{
    public async Task<List<Product>> GetProductsAsync()
    {
        using var db = new SqlSugar.SqlSugarClient(config);
        return await db.Queryable<Product>().ToListAsync();
    }
}

看到了吗?这种写法的问题显而易见:

  • 💀 代码重复率极高

  • 🐛 修改逻辑需要改动多处

  • 📈 维护成本呈指数级增长

  • 🔧 难以进行统一的日志记录和性能监控

🚀 解决方案:构建通用泛型仓储模式

Nuget 安装以下库

SqlSugarCore
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console

实体类

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;

namespace AppSQLBaseRepository
{
    [SugarTable("sys_user")]
    publicclass User
    {
        /// <summary>
        /// 用户ID - 主键
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        publicint Id { get; set; }

        /// <summary>
        /// 用户名 - 唯一索引
        /// </summary>
        [SugarColumn(Length = 50, IsNullable = false)]
        [Required(ErrorMessage = "用户名不能为空")]
        [StringLength(50, ErrorMessage = "用户名长度不能超过50个字符")]
        publicstring UserName { get; set; }

        /// <summary>
        /// 密码哈希值
        /// </summary>
        [SugarColumn(Length = 256, IsNullable = false)]
        [Required(ErrorMessage = "密码不能为空")]
        publicstring PasswordHash { get; set; }

        /// <summary>
        /// 邮箱地址
        /// </summary>
        [SugarColumn(Length = 100, IsNullable = true)]
        [EmailAddress(ErrorMessage = "邮箱格式不正确")]
        [StringLength(100, ErrorMessage = "邮箱长度不能超过100个字符")]
        publicstring Email { get; set; }

        /// <summary>
        /// 手机号码
        /// </summary>
        [SugarColumn(Length = 20, IsNullable = true)]
        [Phone(ErrorMessage = "手机号码格式不正确")]
        [StringLength(20, ErrorMessage = "手机号码长度不能超过20个字符")]
        publicstring PhoneNumber { get; set; }

        /// <summary>
        /// 真实姓名
        /// </summary>
        [SugarColumn(Length = 50, IsNullable = true)]
        [StringLength(50, ErrorMessage = "真实姓名长度不能超过50个字符")]
        publicstring RealName { get; set; }

        /// <summary>
        /// 头像URL
        /// </summary>
        [SugarColumn(Length = 500, IsNullable = true)]
        [StringLength(500, ErrorMessage = "头像URL长度不能超过500个字符")]
        publicstring Avatar { get; set; }

        /// <summary>
        /// 用户状态 (0:禁用 1:启用)
        /// </summary>
        [SugarColumn(IsNullable = false)]
        publicint Status { get; set; } = 1;

        /// <summary>
        /// 是否删除 (0:未删除 1:已删除) - 用于逻辑删除
        /// </summary>
        [SugarColumn(IsNullable = false)]
        publicbool IsDeleted { get; set; } = false;

        /// <summary>
        /// 创建时间
        /// </summary>
        [SugarColumn(IsNullable = false)]
        public DateTime CreateTime { get; set; } = DateTime.Now;

        /// <summary>
        /// 更新时间
        /// </summary>
        [SugarColumn(IsNullable = true)]
        public DateTime? UpdateTime { get; set; }

        /// <summary>
        /// 删除时间
        /// </summary>
        [SugarColumn(IsNullable = false)]
        public DateTime DeleteTime { get; set; }

        /// <summary>
        /// 最后登录时间
        /// </summary>
        [SugarColumn(IsNullable = true)]
        public DateTime? LastLoginTime { get; set; }

        /// <summary>
        /// 创建人
        /// </summary>
        [SugarColumn(IsNullable = true)]
        publicstring? CreatedBy { get; set; }

        /// <summary>
        /// 更新人
        /// </summary>
        [SugarColumn(IsNullable = true)]
        publicstring? UpdatedBy { get; set; }


        /// <summary>
        /// 删除人
        /// </summary>
        [SugarColumn(IsNullable = true)]
        publicstring? DeleteBy { get; set; }

        /// <summary>
        /// 备注信息
        /// </summary>
        [SugarColumn(Length = 500, IsNullable = true)]
        [StringLength(500, ErrorMessage = "备注信息长度不能超过500个字符")]
        publicstring Remark { get; set; }
    }
}

核心接口设计

首先,我们定义一个通用的仓储接口:

其实Sqlsugar自带的已经很牛了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace AppSQLBaseRepository
{

    public interface IBaseRepository<T> where T : class, new()
    {
        #region 查询操作
        Task<T> GetFirstAsync(Expression<Func<T, bool>> whereExpression);
        Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression);
        Task<PageResult<T>> GetPageListAsync(
            Expression<Func<T, bool>> whereExpression,
            PageModel pageModel);
        #endregion

        #region 新增操作
        Task<bool> AddAsync(T entity);
        Task<bool> AddRangeAsync(List<T> entities);
        #endregion

        #region 更新操作
        Task<bool> UpdateAsync(T entity);
        Task<bool> UpdateAsync(
            Expression<Func<T, T>> updateExpression,
            Expression<Func<T, bool>> whereExpression);
        #endregion

        #region 删除操作
        Task<bool> DeleteAsync(Expression<Func<T, bool>> whereExpression);
        Task<bool> FakeDeleteAsync(T entity, Action<T> setDeleteAction);
        #endregion

        #region 聚合操作
        Task<bool> IsExistAsync(Expression<Func<T, bool>> whereExpression);
        Task<int> CountAsync(Expression<Func<T, bool>> whereExpression);
        #endregion
    }
}
🛠️ 核心实现:BaseRepository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using SqlSugar;

namespace AppSQLBaseRepository
{
    publicclass BaseRepository<T> : IBaseRepository<T> where T : class, new()
    {
        protected readonly ISqlSugarClient Db;
        private readonly ILogger<BaseRepository<T>> _logger;

        public BaseRepository(ISqlSugarClient sqlSugarClient, ILogger<BaseRepository<T>> logger)
        {
            Db = sqlSugarClient;
            _logger = logger;

            // 配置SQL日志 - 开发调试神器
            ConfigureSqlLog();
        }

        /// <summary>
        /// 配置SQL执行日志 - 性能监控和问题排查的利器
        /// </summary>
        private void ConfigureSqlLog()
        {
            Db.Aop.OnLogExecuting = (sql, pars) =>
            {
                // 记录SQL执行日志,生产环境可以通过配置控制
                string logMessage = $"SQL执行: {sql}";

                // 记录参数信息(调试时非常有用)
                if (pars?.Length > 0)
                {
                    var paramInfo = string.Join(", ",
                        pars.Select(p => $"{p.ParameterName}={p.Value}"));
                    logMessage += $" | 参数: {paramInfo}";
                }

                _logger.LogDebug(logMessage);
            };
        }

        #region 查询实现

        publicvirtual async Task<T> GetFirstAsync(Expression<Func<T, bool>> whereExpression)
        {
            try
            {
                return await Db.Queryable<T>().Where(whereExpression).FirstAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询单个实体失败");
                throw;
            }
        }

        publicvirtual async Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression)
        {
            try
            {
                return await Db.Queryable<T>().Where(whereExpression).ToListAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询实体列表失败");
                throw;
            }
        }

        /// <summary>
        /// 分页查询实现 - 企业级应用的核心功能
        /// </summary>
        publicvirtual async Task<PageResult<T>> GetPageListAsync(
            Expression<Func<T, bool>> whereExpression,
            PageModel pageModel)
        {
            try
            {
                // 🚀 使用SqlSugar的RefAsync获取总数,一次查询搞定!
                RefAsync<int> totalCount = 0;

                var list = await Db.Queryable<T>()
                    .Where(whereExpression)
                    .ToPageListAsync(
                        pageModel.PageIndex,
                        pageModel.PageSize,
                        totalCount);

                returnnew PageResult<T>
                {
                    PageIndex = pageModel.PageIndex,
                    PageSize = pageModel.PageSize,
                    TotalCount = totalCount,
                    Data = list
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分页查询失败");
                throw;
            }
        }

        #endregion

        #region 新增实现

        publicvirtual async Task<bool> AddAsync(T entity)
        {
            try
            {
                return await Db.Insertable(entity).ExecuteCommandAsync() > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "添加实体失败");
                throw;
            }
        }

        /// <summary>
        /// 批量新增 - 大数据量操作的性能优化
        /// </summary>
        publicvirtual async Task<bool> AddRangeAsync(List<T> entities)
        {
            try
            {
                // 💡 批量插入,性能比逐条插入快10倍以上!
                return await Db.Insertable(entities).ExecuteCommandAsync() > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量添加实体失败");
                throw;
            }
        }

        #endregion

        #region 更新实现

        publicvirtual async Task<bool> UpdateAsync(T entity)
        {
            try
            {
                return await Db.Updateable(entity).ExecuteCommandAsync() > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新实体失败");
                throw;
            }
        }

        publicvirtual async Task<bool> UpdateAsync(
            Expression<Func<T, T>> updateExpression,
            Expression<Func<T, bool>> whereExpression)
        {
            try
            {
                return await Db.Updateable<T>()
                    .SetColumns(updateExpression)
                    .Where(whereExpression)
                    .ExecuteCommandAsync() > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "条件更新失败");
                throw;
            }
        }

        #endregion

        #region 删除实现

        publicvirtual async Task<bool> DeleteAsync(Expression<Func<T, bool>> whereExpression)
        {
            try
            {
                return await Db.Deleteable<T>().Where(whereExpression).ExecuteCommandAsync() > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除实体失败");
                throw;
            }
        }

        /// <summary>
        /// 逻辑删除 - 推荐做法,保证数据安全
        /// </summary>
        publicvirtual async Task<bool> FakeDeleteAsync(T entity, Action<T> setDeleteAction)
        {
            try
            {
                // 🎯 执行自定义的删除逻辑设置
                setDeleteAction(entity);
                return await UpdateAsync(entity);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "逻辑删除失败");
                throw;
            }
        }

        #endregion

        #region 聚合操作实现

        publicvirtual async Task<bool> IsExistAsync(Expression<Func<T, bool>> whereExpression)
        {
            try
            {
                return await Db.Queryable<T>().Where(whereExpression).AnyAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查实体存在性失败");
                throw;
            }
        }

        publicvirtual async Task<int> CountAsync(Expression<Func<T, bool>> whereExpression)
        {
            try
            {
                return await Db.Queryable<T>().Where(whereExpression).CountAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "统计实体数量失败");
                throw;
            }
        }

        #endregion
    }
}

💼 实战应用:看看效果如何

分页模型定义

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppSQLBaseRepository
{
    /// <summary>
    /// 分页请求模型
    /// </summary>
    publicclass PageModel
    {
        publicint PageIndex { get; set; } = 1;
        publicint PageSize { get; set; } = 10;
    }

    /// <summary>
    /// 分页结果模型
    /// </summary>
    publicclass PageResult<T>
    {
        publicint PageIndex { get; set; }
        publicint PageSize { get; set; }
        publicint TotalCount { get; set; }
        public List<T> Data { get; set; }

        /// <summary>
        /// 总页数
        /// </summary>
        publicint TotalPages => (int)Math.Ceiling((double)TotalCount / PageSize);
    }
}

业务层使用示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppSQLBaseRepository
{
    publicclass UserService
    {
        private readonly IBaseRepository<User> _userRepository;

        public UserService(IBaseRepository<User> userRepository)
        {
            _userRepository = userRepository;
        }

        /// <summary>
        /// 获取活跃用户列表 - 一行代码搞定!
        /// </summary>
        public async Task<List<User>> GetActiveUsersAsync()
        {
            return await _userRepository.GetListAsync(
                user => user.Status == 1 && user.IsDeleted == false);
        }

        /// <summary>
        /// 分页获取用户 - 企业级应用标配
        /// </summary>
        public async Task<PageResult<User>> GetUsersPageAsync(PageModel pageModel)
        {
            return await _userRepository.GetPageListAsync(
                user => user.IsDeleted == false,
                pageModel);
        }

        /// <summary>
        /// 批量导入用户 - 性能优化实践
        /// </summary>
        public async Task<bool> BatchImportUsersAsync(List<User> users)
        {
            return await _userRepository.AddRangeAsync(users);
        }

        /// <summary>
        /// 逻辑删除用户 - 数据安全第一
        /// </summary>
        public async Task<bool> SoftDeleteUserAsync(User user)
        {
            return await _userRepository.FakeDeleteAsync(user, entity =>
            {
                entity.IsDeleted = true;
                entity.DeleteTime = DateTime.Now;
                entity.DeleteBy = "System"; 
            });
        }
    }
}

⚡ 依赖注入配置

Program.csStartup.cs中注册服务:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SqlSugar;

namespace AppSQLBaseRepository
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            // 服务容器
            var services = new ServiceCollection();

            // 添加日志服务
            services.AddLogging(builder =>
            {
                builder.AddConsole();
                builder.SetMinimumLevel(LogLevel.Information);
            });

            // 注册SqlSugar
            services.AddSingleton<ISqlSugarClient>(provider =>
            {
                returnnew SqlSugarClient(new ConnectionConfig
                {
                    ConnectionString = "Server=localhost;Database=dbtest;User Id=sa;Password=123;TrustServerCertificate=true;",  // 应从配置文件读取
                    DbType = DbType.SqlServer,
                    IsAutoCloseConnection = true
                });
            });

            // 注册泛型仓储
            services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));

            // 注册业务服务
            services.AddScoped<UserService>();

            // 构建服务提供者
            var serviceProvider = services.BuildServiceProvider();

            // 实际使用UserService
            using (var scope = serviceProvider.CreateScope())
            {
                var userService = scope.ServiceProvider.GetRequiredService<UserService>();
                // 调用 userService 方法
                var list = await userService.GetUsersPageAsync(new PageModel { PageIndex = 1, PageSize = 10 });
                foreach (var item in list.Data)
                {
                    Console.WriteLine(item.UserName);
                    Console.WriteLine(item.Email);
                    Console.WriteLine(item.PhoneNumber);
                    Console.WriteLine(item.RealName);
                }
            }
        }
    }
}

🎯 进阶技巧与最佳实践

1. 性能优化建议

// ✅ 推荐:使用批量操作
await _repository.AddRangeAsync(largeUserList);

// ❌ 避免:循环单条操作
foreach(var user in largeUserList)
{
    await _repository.AddAsync(user); // 性能杀手!
}

2. 常见坑点提醒

⚠️ 注意事项:

  • 始终使用异步方法,提升应用吞吐量

  • 大数据量操作时优先考虑批量方法

  • 生产环境记得关闭SQL日志输出

  • 合理使用表达式树,避免过于复杂的Lambda表达式

3. 扩展性设计

// 🔥 金句:如果需要特殊业务逻辑,继承BaseRepository即可
public class UserRepository : BaseRepository<User>, IUserRepository
{
    public UserRepository(ISqlSugarClient client, ILogger<UserRepository> logger) 
        : base(client, logger) { }

    // 添加用户特有的业务方法
    public async Task<List<User>> GetUsersByDepartmentAsync(int departmentId)
    {
        return await Db.Queryable<User>()
            .Where(u => u.DepartmentId == departmentId)
            .OrderBy(u => u.CreateTime)
            .ToListAsync();
    }
}

🎊 总结:三大核心收益

通过实施这套泛型仓储模式,你将获得:

  1. 📈 开发效率提升80%

    告别重复代码,专注业务逻辑

  2. 🛡️ 代码质量飞跃

    统一的数据访问模式,降低bug率

  3. 🚀 维护成本骤降

    一处修改,全局生效,扩展性极强

收藏级代码模板已经为你准备好了! 这套方案已在多个企业级项目中验证,能够显著提升团队的开发效率和代码质量。


💬 互动讨论

  1. 你在项目中是如何处理数据访问层重复代码问题的?

  2. 对于这套泛型仓储模式,你觉得还有哪些可以优化的地方?