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
中配置的连接字符串正确,否则无法建立数据库连接。在不同的环境(开发、测试、生产)中,要注意切换相应的配置。 - 实体类特性使用:使用
SugarTable
和SugarColumn
等特性时,要准确设置属性,避免因特性设置错误导致数据库表结构创建或数据映射出现问题。 - 单例模式的影响:
ISqlSugarClient
以单例模式注册,在多线程环境下要注意线程安全问题,虽然 SqlSugar 本身在设计上考虑了多线程场景,但在复杂的业务逻辑中,仍需谨慎处理共享资源的访问。
通过以上对 SqlSugar 结合依赖注入与仓储模式的代码分析和示例展示,相信大家对如何在 C# 项目中高效地进行数据库操作有了更深入的了解。合理运用这些技术,能够让我们的项目在数据访问层面更加稳健和灵活,为整个应用的稳定运行提供有力支持。如果你在实际使用过程中遇到问题或有更好的实践经验,欢迎在评论区交流分享。
上述博客详细讲解了代码的功能与应用。若你觉得内容还需补充,比如增加更多复杂操作示例或优化说明,可随时告知我。