文件内容 ReadWriteSplitInterceptor.cs 4 KB 4133 字符
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using PasteApeart.Domain;
using System.Data.Common;

namespace PasteApeart.EntityFrameworkCore
{
    /// <summary>
    /// 
    /// </summary>
    public class ReadWriteSplitInterceptor : DbConnectionInterceptor
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IConfiguration _configuration;
        private readonly ReadOnlyOption _config;

        /*       
            services.AddSingleton<ReadWriteSplitInterceptor>();
            services.AddDbContext<SqliteDb>((sp, options) =>
            {
                options.UseSqlite(configuration.GetConnectionString(PasteApeartDbProperties.SqliteConnectionStringName));
                //读写分离 如果不需要那么用上面的,或者下面2行注释掉即可
                var rwp = sp.GetRequiredService<ReadWriteSplitInterceptor>();
                options.AddInterceptors(rwp);
            });
         */


        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <param name="config"></param>
        /// <param name="readConfig"></param>
        public ReadWriteSplitInterceptor(IHttpContextAccessor serviceProvider, IConfiguration config,IOptions<ReadOnlyOption> readConfig)
        {

            _httpContextAccessor = serviceProvider;
            _configuration = config;
            _config = readConfig.Value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="eventData"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)
        {
            var isReadOnly = _httpContextAccessor.HttpContext?.Items["IsReadOnly"] as bool? ?? false;
            if (isReadOnly)
            {
                connection.ConnectionString = _configuration.GetConnectionString(_config.CurrentReadStringName);
            }
            else
            {
                connection.ConnectionString = _configuration.GetConnectionString(_config.CurrentMainStringName);
            }
            //var connectName = _httpContextAccessor.HttpContext?.Items["ConnectName"] as string ?? string.Empty;
            //if (!string.IsNullOrEmpty(connectName))
            //{
            //    connection.ConnectionString = _configuration.GetConnectionString(connectName);
            //}
            return base.ConnectionOpening(connection, eventData, result);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="eventData"></param>
        /// <param name="result"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override ValueTask<InterceptionResult> ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)
        {
            var isReadOnly = _httpContextAccessor.HttpContext?.Items["IsReadOnly"] as bool? ?? false;
            if (isReadOnly)
            {
                connection.ConnectionString = _configuration.GetConnectionString(_config.CurrentReadStringName);
            }
            else
            {
                connection.ConnectionString = _configuration.GetConnectionString(_config.CurrentMainStringName);
            }
            //var connectName = _httpContextAccessor.HttpContext?.Items["ConnectName"] as string ?? string.Empty;
            //if (!string.IsNullOrEmpty(connectName))
            //{
            //    connection.ConnectionString = _configuration.GetConnectionString(connectName);
            //}
            return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);
        }

        //使用案例 先注入ReadWriteSplitInterceptor 应该是Icope
    }

}
​ ​