首页 新闻 会员 周边 捐助

EntityFramework6.0 DbCommandInterceptor 拦截器实现读写分离

0
悬赏园豆:50 [已关闭问题] 关闭于 2016-09-01 22:14
复制代码
 public class DbMasterSlaveCommandInterceptor1 : DbCommandInterceptor
    {
        private string masterConnectionString = ConfigurationManager.ConnectionStrings["masterConnectionString"].ToString();
        private string slaveConnectionString = ConfigurationManager.ConnectionStrings["slaveConnectionString"].ToString();

        public string MasterConnectionString
        {
            get
            {
                return this.masterConnectionString;
            }
        }

        public string SlaveConnectionString
        {
            get
            {
                return this.slaveConnectionString;
            }
        }

        public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            base.NonQueryExecuting(command, interceptionContext);//update,delete等写操作直接走主库
        }

        public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            base.NonQueryExecuted(command, interceptionContext);
            command.Parameters.Clear();
        }

        public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            this.UpdateToSlave(command, interceptionContext);
            base.ReaderExecuting(command, interceptionContext);
        }

        public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            base.ReaderExecuted(command, interceptionContext);
            command.Parameters.Clear();
        }

        public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
            this.UpdateToSlave(command, interceptionContext);
            base.ScalarExecuting(command, interceptionContext);
        }

        public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
            base.ScalarExecuted(command, interceptionContext);
            command.Parameters.Clear();
        }


        private void UpdateToSlave(DbCommand command, DbInterceptionContext interceptionContext)
        {
            if (command.CommandText.ToLower().StartsWith("insert", StringComparison.InvariantCultureIgnoreCase) == false)
            {
                // 判断当前会话是否处于分布式事务中
                bool isDistributedTran = Transaction.Current != null &&
                                         Transaction.Current.TransactionInformation.Status !=
                                         TransactionStatus.Committed;
                foreach (var context in interceptionContext.DbContexts)
                {
                    //判断该 context 是否处于普通数据库事务中
                    bool isDbTran = context.Database.CurrentTransaction != null;

                    // 如果处于分布式事务或普通事务中,则“禁用”读写分离,处于事务中的所有读写操作都指向 Master
                    string connectionString = isDistributedTran || isDbTran ? this.MasterConnectionString : this.SlaveConnectionString;
                    if (command.Connection.State == ConnectionState.Open)
                    {
                        command.Connection.Close();
                    }
                    command.Connection.ConnectionString = connectionString;
                    command.Connection.Open();
                }
            }
        }

    }
复制代码

 

 protected void Application_Start()
{
 
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    DbInterception.Add(new DbMasterSlaveCommandInterceptor1());//开启主从模式
 
}

 

 

此处可以实现读写分离,一切都OK,唯一的问题就是从库上打开的链接不能自动close掉,不知有谁遇到过没?

< >
分享
所有回答(1)
0

你主动打开的连接。自己关掉就可以了吧。至于为什么没有关,也不是很清楚。

| 园豆:780 (小虾三级) | 2016-08-15 21:06
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册