.NET 集成 SqlSugar、读写分离 、Redis

一、环境准备(NuGet 安装)

 

# SqlSugar 核心
Install-Package SqlSugarCore
# Redis 驱动 (StackExchange.Redis 官方推荐)
Install-Package StackExchange.Redis
# 缓存工具包
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis

   


 

二、appsettings.json 配置

 

{
  "ConnectionStrings": {
    // 主库(写入、更新、删除)
    "MasterDb": "Server=.;Database=TestDb;Uid=root;Pwd=123456;",
    // 从库(只读,可配置多个)
    "SlaveDb": "Server=.;Database=TestDb;Uid=root;Pwd=123456;",
    // Redis
    "Redis": "127.0.0.1:6379,password=,defaultDatabase=0"
  }
}

   


 

三、SqlSugar 读写分离配置

 

1. 注册 SqlSugar(Program.cs)

 

var builder = WebApplication.CreateBuilder(args);

// 1. 注册 SqlSugar + 读写分离
builder.Services.AddSingleton<ISqlSugarClient>(provider =>
{
    var config = new ConnectionConfig()
    {
        // 主库
        ConnectionString = builder.Configuration.GetConnectionString("MasterDb"),
        DbType = DbType.MySql, // 根据你的数据库改:SqlServer/PostgreSQL
        IsAutoCloseConnection = true,

        // ===================== 读写分离配置 =====================
        SlaveConnectionConfigs = new List<SlaveConnectionConfig>()
        {
            new SlaveConnectionConfig()
            {
                ConnectionString = builder.Configuration.GetConnectionString("SlaveDb"),
                HitRate = 100 // 权重(多从库可分配比例)
            }
        }
    };

    return new SqlSugarClient(config);
});

// 2. 注册 Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration.GetConnectionString("Redis");
});

builder.Services.AddControllers();

   


 

四、读写分离使用规则(自动切换)

  SqlSugar 完全自动切换主从库,你不用手动控制:  

自动规则

 

  • 查询(Select) → 自动走 从库
  • 增删改(Insert/Update/Delete) → 自动走 主库
  • 事务内所有操作 → 强制走 主库

 

基础使用示例(Service 层)

 

public class UserService
{
    private readonly ISqlSugarClient _db;

    public UserService(ISqlSugarClient db)
    {
        _db = db;
    }

    // ========== 读:自动走从库 ==========
    public async Task<User> GetUserAsync(int id)
    {
        return await _db.Queryable<User>().In(id).FirstAsync();
    }

    // ========== 写:自动走主库 ==========
    public async Task<bool> AddUserAsync(User user)
    {
        return await _db.Insertable(user).ExecuteCommandAsync() > 0;
    }

    public async Task<bool> UpdateUserAsync(User user)
    {
        return await _db.Updateable(user).ExecuteCommandAsync() > 0;
    }
}

   


 

五、Redis 缓存基础使用

  结合读写分离,实现 “先查缓存 → 缓存没有再查从库 → 存入缓存”  

1. 封装 Redis 帮助类

 

public class RedisCacheService
{
    private readonly IDistributedCache _cache;

    public RedisCacheService(IDistributedCache cache)
    {
        _cache = cache;
    }

    // 获取缓存
    public async Task<T> GetAsync<T>(string key)
    {
        var value = await _cache.GetStringAsync(key);
        return value == null ? default : JsonSerializer.Deserialize<T>(value);
    }

    // 设置缓存(带过期时间)
    public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
    {
        expiry ??= TimeSpan.FromMinutes(10); // 默认10分钟
        await _cache.SetStringAsync(key, JsonSerializer.Serialize(value), new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = expiry
        });
    }

    // 删除缓存
    public async Task RemoveAsync(string key)
    {
        await _cache.RemoveAsync(key);
    }
}

 

2. 注册 Redis 帮助类

 

builder.Services.AddScoped<RedisCacheService>();

   


 

六、最终:读写分离 + Redis 整合(最佳实践)

 

public class UserService
{
    private readonly ISqlSugarClient _db;
    private readonly RedisCacheService _cache;

    public UserService(ISqlSugarClient db, RedisCacheService cache)
    {
        _db = db;
        _cache = cache;
    }

    /// <summary>
    /// 缓存 + 从库查询
    /// </summary>
    public async Task<User> GetUserWithCacheAsync(int userId)
    {
        var cacheKey = $"user:{userId}";

        // 1. 先查 Redis
        var user = await _cache.GetAsync<User>(cacheKey);
        if (user != null) return user;

        // 2. Redis 没有 → 查 从库
        user = await _db.Queryable<User>().In(userId).FirstAsync();
        if (user == null) return null;

        // 3. 存入 Redis(10分钟过期)
        await _cache.SetAsync(cacheKey, user);

        return user;
    }

    /// <summary>
    /// 更新数据 → 主库 + 删除缓存
    /// </summary>
    public async Task<bool> UpdateUserAsync(User user)
    {
        // 走主库
        var result = await _db.Updateable(user).ExecuteCommandAsync() > 0;

        if (result)
        {
            // 更新成功 → 删除旧缓存
            await _cache.RemoveAsync($"user:{user.Id}");
        }

        return result;
    }
}

   


 

七、强制指定主库 / 从库(特殊场景)

  如果你需要手动控制:  

// 强制走主库查询
await _db.Queryable<User>().With(SqlWith.Master).ToListAsync();

// 强制走从库
await _db.Queryable<User>().With(SqlWith.Slave).ToListAsync();

文章摘自:https://www.cnblogs.com/chuansheng/p/19913845