Example #1
0
        /// <summary>
        /// 若使用【读写分离】,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
        /// </summary>
        /// <param name="readerHander"></param>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="cmdParms"></param>
        /// <returns></returns>
        async public Task ExecuteReaderAsync(Func <NpgsqlDataReader, Task> readerHander, CommandType cmdType, string cmdText, params NpgsqlParameter[] cmdParms)
        {
            DateTime dt        = DateTime.Now;
            string   logtxt    = "";
            DateTime logtxt_dt = DateTime.Now;
            var      pool      = this.MasterPool;
            bool     isSlave   = false;

            //读写分离规则
            if (this.SlavePools.Any() && cmdText.StartsWith("SELECT ", StringComparison.CurrentCultureIgnoreCase))
            {
                var availables = slaveUnavailables == 0 ?
                                 //查从库
                                 this.SlavePools : (
                    //查主库
                    slaveUnavailables == this.SlavePools.Count ? new List <NpgsqlConnectionPool>() :
                    //查从库可用
                    this.SlavePools.Where(sp => sp.IsAvailable).ToList());
                if (availables.Any())
                {
                    isSlave = true;
                    pool    = availables.Count == 1 ? this.SlavePools[0] : availables[slaveRandom.Next(availables.Count)];
                }
            }

            Object <NpgsqlConnection> conn = null;
            NpgsqlCommand             cmd  = PrepareCommandAsync(cmdType, cmdText, cmdParms, ref logtxt);

            if (IsTracePerformance)
            {
                logtxt += $"PrepareCommand: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
            }
            Exception ex = null;

            try {
                if (IsTracePerformance)
                {
                    logtxt_dt = DateTime.Now;
                }
                if (isSlave)
                {
                    //从库查询切换,恢复
                    bool isSlaveFail = false;
                    try {
                        if (cmd.Connection == null)
                        {
                            cmd.Connection = (conn = await pool.GetAsync()).Value;
                        }
                        //if (slaveRandom.Next(100) % 2 == 0) throw new Exception("测试从库抛出异常");
                    } catch {
                        isSlaveFail = true;
                    }
                    if (isSlaveFail)
                    {
                        if (conn != null)
                        {
                            if (IsTracePerformance)
                            {
                                logtxt_dt = DateTime.Now;
                            }
                            pool.Return(conn, ex);
                            if (IsTracePerformance)
                            {
                                logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
                            }
                        }
                        LoggerException(pool, cmd, new Exception($"连接失败,准备切换其他可用服务器"), dt, logtxt, false);
                        cmd.Parameters.Clear();
                        await ExecuteReaderAsync(readerHander, cmdType, cmdText, cmdParms);

                        return;
                    }
                }
                else
                {
                    //主库查询
                    if (cmd.Connection == null)
                    {
                        cmd.Connection = (conn = await pool.GetAsync()).Value;
                    }
                }
                if (IsTracePerformance)
                {
                    logtxt   += $"Open: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
                    logtxt_dt = DateTime.Now;
                }
                using (NpgsqlDataReader dr = await cmd.ExecuteReaderAsync() as NpgsqlDataReader) {
                    if (IsTracePerformance)
                    {
                        logtxt += $"ExecuteReader: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
                    }
                    while (true)
                    {
                        if (IsTracePerformance)
                        {
                            logtxt_dt = DateTime.Now;
                        }
                        bool isread = await dr.ReadAsync();

                        if (IsTracePerformance)
                        {
                            logtxt += $"	dr.Read: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
                        }
                        if (isread == false)
                        {
                            break;
                        }

                        if (readerHander != null)
                        {
                            object[] values = null;
                            if (IsTracePerformance)
                            {
                                logtxt_dt = DateTime.Now;
                                values    = new object[dr.FieldCount];
                                for (int a = 0; a < values.Length; a++)
                                {
                                    if (!await dr.IsDBNullAsync(a))
                                    {
                                        values[a] = await dr.GetFieldValueAsync <object>(a);
                                    }
                                }
                                logtxt   += $"	dr.GetValues: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
                                logtxt_dt = DateTime.Now;
                            }
                            await readerHander(dr);

                            if (IsTracePerformance)
                            {
                                logtxt += $"	readerHander: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms ({string.Join(",", values)})\r\n";
                            }
                        }
                    }
                    if (IsTracePerformance)
                    {
                        logtxt_dt = DateTime.Now;
                    }
                    dr.Close();
                }
                if (IsTracePerformance)
                {
                    logtxt += $"ExecuteReader_dispose: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
                }
            } catch (Exception ex2) {
                ex = ex2;
            }

            if (conn != null)
            {
                if (IsTracePerformance)
                {
                    logtxt_dt = DateTime.Now;
                }
                pool.Return(conn, ex);
                if (IsTracePerformance)
                {
                    logtxt += $"ReleaseConnection: {DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds}ms Total: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms";
                }
            }
            LoggerException(pool, cmd, ex, dt, logtxt);
            cmd.Parameters.Clear();
        }