C# SqlSugar:依赖注入与仓储模式实践

发布于:2025-06-10 ⋅ 阅读:(22) ⋅ 点赞:(0)

C# SqlSugar:依赖注入与仓储模式实践

在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受欢迎的一款。它不仅功能强大,还能结合依赖注入和仓储模式,让代码结构更加清晰。接下来,我们就深入剖析一段利用 SqlSugar 实现依赖注入与仓储模式的代码,了解其原理与使用方式。

一、核心代码解析

1. 基础实体类定义

public abstract class BaseEntity
{
   [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
   public virtual int Id { get; set; }
}

BaseEntity作为基础实体类,定义了一个自增长的主键Id,通过SugarColumn特性设置Id为自增主键,后续的实体类都可以继承该类,统一规范实体的基本属性,为数据库表的主键设置提供便利。

2. 仓储类实现

public class Repository<T> : SimpleClient<T> where T : BaseEntity, new()
{
   public Repository(ISqlSugarClient db)
   {
       base.Context = db;
   }
}

Repository<T>类继承自SimpleClient<T>,它是基于 SqlSugar 实现的泛型仓储类。通过构造函数接收ISqlSugarClient类型的数据库客户端实例db,并将其赋值给基类的Context属性,这样在该仓储类中就可以使用SqlSugar提供的各种数据库操作方法,对继承自BaseEntity的实体类T进行数据访问和操作,实现了对数据库操作的封装,符合仓储模式的理念。

3. SqlSugar 初始化配置

public static class SqlSugarInit
{
   private static readonly string connectionKey = "database_connection_key";
   public static void AddSqlSugarSetup(this IServiceCollection services)
   {
       if (services is null)
       {
           throw new ArgumentNullException(nameof(services));
       }


       var config = GetConfig(connectionKey);
       var client = new SqlSugarScope(config);
       services.AddSingleton<ISqlSugarClient>(o => client);

       var models = GetEntities();
       client.DbMaintenance.CreateDatabase();
       client.CodeFirst.SetStringDefaultLength(200).InitTables(models);
   }


   private static ConnectionConfig GetConfig(string connectionKey)
   {
       var connectionString = ConfigurationManager.ConnectionStrings\[connectionKey].ConnectionString;
       var moreSettings = new ConnMoreSettings
       {
           IsAutoRemoveDataCache = true,
           DisableMillisecond = true,
           IsWithNoLockQuery = true,
           SqliteCodeFirstEnableDefaultValue = true,
       };


       var aopEvents = new AopEvents
       {
           OnLogExecuting = (sql, parameters) =>
           {
               parameters.ToList().ForEach(p => sql.Replace(p.ParameterName, p.Value.ToString()));
               var log = string.Join("\r\n", new string[] { "--------", "【SQL语句】:", sql });
               Console.WriteLine(log);
           },
       };


       return new ConnectionConfig
       {
           ConfigId = 1,
           ConnectionString = connectionString,
           DbType = DbType.SqlServer,
           IsAutoCloseConnection = true,
           InitKeyType = InitKeyType.Attribute,
           MoreSettings = moreSettings,
           AopEvents = aopEvents,
           LanguageType = LanguageType.Chinese
       };
   }


   private static Type[] GetEntities()
   {
       return Assembly.GetExecutingAssembly()
          .GetReferencedAssemblies()
          .Select(a => Assembly.Load(a))
          .SelectMany(a => a.GetTypes())
          .Where(t => t.IsSubclassOf(typeof(BaseEntity)))
          .Where(t => t.GetCustomAttributes().Any(a => a is SugarTable))
          .ToArray();
   }
}

SqlSugarInit类负责 SqlSugar 的初始化配置和依赖注入相关操作:

  • AddSqlSugarSetup方法通过扩展IServiceCollection,将 SqlSugar 配置添加到服务集合中。它先获取数据库连接配置config,创建SqlSugarScope实例client,并将ISqlSugarClient以单例模式注册到服务集合,保证整个应用中只有一个SqlSugarClient实例。接着获取所有符合条件的实体类models,使用DbMaintenance.CreateDatabase创建数据库(如果不存在),并通过CodeFirst初始化数据库表结构。
  • GetConfig方法用于获取数据库连接配置信息,从配置文件中读取连接字符串,设置连接的额外参数moreSettings和 AOP 事件aopEvents(这里实现了 SQL 语句执行日志输出功能),最终返回完整的ConnectionConfig对象。
  • GetEntities方法通过反射,从当前程序集及其引用的程序集中,筛选出继承自BaseEntity且带有SugarTable特性的实体类类型数组,以便后续进行数据库表的初始化操作。

二、使用示例

1. 假设我们有一个User实体类:

using SqlSugar;

[SugarTable("Users")]

public class User : BaseEntity
{
   public string Name { get; set; }
   public int Age { get; set; }
}

2. 在应用的启动配置中,注册 SqlSugar 服务:

using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();
services.AddSqlSugarSetup();
services.AddScoped(typeof(Repository<>));

var serviceProvider = services.BuildServiceProvider();

3. 在业务逻辑中使用仓储类进行数据操作:

class UserService
{
    private readonly Repository<User> userRepository;
    public UserService(Repository<User> userRepository)
    {
        this.userRepository = userRepository;
    }

    public User FindOne(int id)
    {
        return this.userRepository.GetById(id);
    }
}

上述代码中,先创建User实体类并继承BaseEntity,使用SugarTable特性指定数据库表名。在启动配置时,注册 SqlSugar 服务和User实体类对应的仓储服务。在业务逻辑中获取User仓储实例,进行数据插入和查询操作,简洁地实现了数据库交互。

三、优势与注意事项

1. 优势

  • 代码结构清晰:依赖注入和仓储模式的结合,将数据库操作与业务逻辑分离,降低了代码的耦合度,使代码结构更加清晰,便于维护和扩展。
  • 提高开发效率:SqlSugar 提供了丰富的数据库操作方法,通过仓储类的封装,开发者无需重复编写基础的数据访问代码,提高了开发效率。
  • 统一规范BaseEntity类和统一的配置方式,为实体类和数据库操作建立了统一的规范,保证了代码的一致性和规范性。

2. 注意事项

  • 数据库连接字符串配置:确保ConfigurationManager.ConnectionStrings中配置的连接字符串正确,否则无法建立数据库连接。在不同的环境(开发、测试、生产)中,要注意切换相应的配置。
  • 实体类特性使用:使用SugarTableSugarColumn等特性时,要准确设置属性,避免因特性设置错误导致数据库表结构创建或数据映射出现问题。
  • 单例模式的影响ISqlSugarClient以单例模式注册,在多线程环境下要注意线程安全问题,虽然 SqlSugar 本身在设计上考虑了多线程场景,但在复杂的业务逻辑中,仍需谨慎处理共享资源的访问。

通过以上对 SqlSugar 结合依赖注入与仓储模式的代码分析和示例展示,相信大家对如何在 C# 项目中高效地进行数据库操作有了更深入的了解。合理运用这些技术,能够让我们的项目在数据访问层面更加稳健和灵活,为整个应用的稳定运行提供有力支持。如果你在实际使用过程中遇到问题或有更好的实践经验,欢迎在评论区交流分享。

上述博客详细讲解了代码的功能与应用。若你觉得内容还需补充,比如增加更多复杂操作示例或优化说明,可随时告知我。