コード例 #1
0
        public Task <DbConnection> GetDbConnectionAsync(string poolKey)
        {
            if (disposedValue)
            {
                throw new ObjectDisposedException(nameof(SqlConnectionPoolManager));
            }

            if (!_poolOptions.ContainsKey(poolKey))
            {
                throw new KeyNotFoundException();
            }

            var pool = _pools[poolKey];
            PooledDbConnectionWrapper availableConn = null;

            do
            {
                var hasConn = TryGetConnection(pool, out availableConn, out _);

                if (!hasConn && !SetupNewConnection(poolKey))
                {
                    break;
                }
            }while (availableConn?.DbConnection.State != ConnectionState.Open);

            return(Task.FromResult(availableConn?.DbConnection));
        }
コード例 #2
0
        public Task <bool> TryReturnToPoolAsync(DbConnection connection)
        {
            if (disposedValue || !connection.CanOpen())
            {
                return(Task.FromResult(false));
            }

            if (connection is SqlConnection == false)
            {
                throw new InvalidOperationException("Unsupported connection");
            }

            var sqlConn = connection as SqlConnection;

            var poolKey = GetPoolKeyFromConnStr(sqlConn.ConnectionString);

            if (!_poolOptions.ContainsKey(poolKey))
            {
                return(Task.FromResult(false));
            }

            var wrapper = new PooledDbConnectionWrapper(connection, poolKey);

            return(TryReturnToPoolAsync(wrapper));
        }
コード例 #3
0
        private async Task DbConn_StateChangeAsync(object sender, StateChangeEventArgs e,
                                                   PooledDbConnectionWrapper wrapper)
        {
            if (disposedValue || wrapper.DbConnection.IsOpening() ||
                HasExceededLifetime(
                    _connInfos[(wrapper.DbConnection as SqlConnection).ClientConnectionId],
                    _poolOptions[wrapper.PoolKey]))
            {
                return;
            }

            await TryReturnToPoolAsync(wrapper);
        }
コード例 #4
0
        private bool TryGetConnection(ConcurrentQueue <PooledDbConnectionWrapper> pool,
                                      out PooledDbConnectionWrapper wrapper,
                                      out ConnectionInfo connectionInfo)
        {
            connectionInfo = default;
            var hasConn = pool.TryDequeue(out wrapper);

            if (hasConn)
            {
                _connInfos.Remove((wrapper.DbConnection as SqlConnection).ClientConnectionId, out connectionInfo);
                wrapper.IsInPool = false;
            }

            return(hasConn);
        }
コード例 #5
0
        private bool SetupNewConnection(string poolKey)
        {
            if (disposedValue)
            {
                return(false);
            }

            lock (_poolsLock)
            {
                var pool       = _pools[poolKey];
                var poolOption = _poolOptions[poolKey];

                if (HasFullOfConnections(pool, poolOption))
                {
                    return(false);
                }

                try
                {
                    var dbConn  = new SqlConnection(poolOption.ConnectionString);
                    var wrapper = new PooledDbConnectionWrapper(dbConn, poolKey);

                    dbConn.StateChange += async(sender, e) => await DbConn_StateChangeAsync(sender, e, wrapper);

                    dbConn.Open();

                    AddNewConnection(pool, wrapper);
                }
                catch (Exception ex)
                {
                    NewConnectionError?.Invoke(ex, poolKey);
                    throw ex;
                }
            }

            return(true);
        }
コード例 #6
0
 private void AddNewConnection(ConcurrentQueue <PooledDbConnectionWrapper> pool, PooledDbConnectionWrapper wrapper)
 {
     pool.Enqueue(wrapper);
     _connInfos[(wrapper.DbConnection as SqlConnection).ClientConnectionId] = new ConnectionInfo()
     {
         CreatedTime = DateTime.UtcNow,
         Wrapper     = wrapper
     };
     wrapper.IsInPool = true;
 }
コード例 #7
0
        private Task <bool> TryReturnToPoolAsync(PooledDbConnectionWrapper wrapper)
        {
            if (disposedValue || !wrapper.DbConnection.CanOpen())
            {
                return(Task.FromResult(false));
            }

            return(Task.Run(() =>
            {
                if (disposedValue || !wrapper.DbConnection.CanOpen())
                {
                    return false;
                }

                var poolKey = wrapper.PoolKey;
                var poolOption = _poolOptions[poolKey];
                var pool = _pools[poolKey];
                var inPool = false;

                RetryAction((retryCount) =>
                {
                    try
                    {
                        lock (_poolsLock)
                        {
                            if (!HasFullOfConnections(pool, poolOption))
                            {
                                if (wrapper.IsInPool)
                                {
                                    if (HasExceededLifetime(
                                            _connInfos[(wrapper.DbConnection as SqlConnection).ClientConnectionId],
                                            poolOption))
                                    {
                                        return true;
                                    }

                                    if (!wrapper.DbConnection.IsOpening() && wrapper.DbConnection.CanOpen())
                                    {
                                        wrapper.DbConnection.Open();
                                    }
                                }
                                else
                                {
                                    if (!wrapper.DbConnection.IsOpening() && wrapper.DbConnection.CanOpen())
                                    {
                                        wrapper.DbConnection.Open();
                                    }

                                    AddNewConnection(pool, wrapper);
                                }

                                inPool = true;
                            }

                            return true;
                        }
                    }
                    catch (Exception ex)
                    {
                        TryReturnToPoolError?.Invoke(ex, retryCount);
                        return false;
                    }
                }, poolOption);

                return inPool;
            }));
        }