ABP Vnext(.net8) + MySQL实现读写分离

#! MySQL先配置主从复制,可参照主从复制

1. 在appsettings.json中增加以下配置。

"ConnectionStrings": {
  "Default": "Server=localhost;Port=3307;Database=数据库名称;Uid=root;Pwd=密码;",
  "ReadDb": "Server=localhost;Port=3308;Database=数据库名称;Uid=root;Pwd=密码;"
}

2. 在Application层增加CustomActionFilterAttribute.cs文件

// ActionFilterAttribute命名空间:Microsoft.AspNetCore.Mvc.Filters
public class CustomActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);

        // 确保ActionDescriptor是ControllerActionDescriptor的实例  
        if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
        {
            // 获取控制器动作方法的MethodInfo  
            MethodInfo methodInfo = controllerActionDescriptor.MethodInfo;

            // 检查方法上是否存在[ReadOnly(true)]属性  
            var readOnlyAttribute = methodInfo.GetCustomAttributes(typeof(ReadOnlyAttribute), false)
                                             .Cast<ReadOnlyAttribute>()
                                             .FirstOrDefault();

            if (readOnlyAttribute != null && readOnlyAttribute.IsReadOnly)
            {
                // 设置一个标记,表明这是一个只读操作  
                // 你可以将标记存储在HttpContext中,以便后续使用  
                context.HttpContext.Items["IsReadOnlyOperation"] = true;

                // 也可以在这里执行其他逻辑,比如改变数据库连接等  
                // 但请注意,直接在这里改变数据库连接可能不是最佳实践  
                // 通常,你会在服务层中根据这个标记来决定使用哪个数据库连接  
            }
        }
    }
}

3. 在EntityFrameworkCore层增加DbConnectionStringResolver.cs文件

public class DbConnectionStringResolver : IConnectionStringResolver, ITransientDependency
{
    private readonly IConfiguration _configuration;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public DbConnectionStringResolver(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
    {
        _configuration = configuration;
        _httpContextAccessor = httpContextAccessor;
    }

    public string Resolve(string? connectionStringName = null)
    {
        bool isRead = false;
        // 检查HttpContext是否可用  
        if (_httpContextAccessor.HttpContext != null && _httpContextAccessor.HttpContext.Items.ContainsKey("IsReadOnlyOperation"))
        {
            var isReadOnly = (bool)_httpContextAccessor.HttpContext.Items["IsReadOnlyOperation"];
            if (isReadOnly) isRead = true;
        }

        string? connectionString = string.Empty;
        if (isRead) connectionString = _configuration.GetConnectionString("ReadDb");
        else connectionString = _configuration.GetConnectionString("Default");
        return connectionString != null ? connectionString : string.Empty;
    }

    public Task<string> ResolveAsync(string? connectionStringName = null)
    {
        return Task.FromResult(Resolve(connectionStringName));
    }
}

4. 在EntityFrameworkCore层新增ManagementModule.cs文件

[DependsOn(typeof(AbpTenantManagementEntityFrameworkCoreModule))]
public class ManagementModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.Replace(ServiceDescriptor.Transient<IConnectionStringResolver, DbConnectionStringResolver>());

        context.Services.AddDbContext<ManagerDbContext>((serviceProvider, options) =>
        {
            var connectionString = serviceProvider.GetRequiredService<IConnectionStringResolver>().Resolve("Default");
            options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
        });
    }
}

5. 在Application层对应只读方法增加以下配置

[ReadOnly(true)]
[CustomActionFilter]
public Task<PagedResultDto<Dto>> GetListAsync(GetInput input)
{
    // 方法执行
}

# 设置好上述即可。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值