Domanda

I have created a .Net 3.5 web service in C# that communicates to a Progress OpenEdge database through ODBC.

This database has been set up to only allow 10 simultaneous connections on the user account the web service is using (third party restriction).

I am running into a huge problem when the web service gets a lot of simultaneous requests and tries to connect to the database for each of these requests. When the connection limit is exceeded, the database will reject new incoming connections for a couple of minutes.

The web service is running on windows server 2008. Connection pooling is enabled for the ODBC driver.

I somehow will have to restrict the number of connections that my web service is trying to make, but I don't know how. The Progress OpenEdge ODBC driver that I am using, does not support a maximum pool size argument.

I've been reading a lot of documentation from microsoft on the subject, but all I have been able to conclude is:

  • Connection pooling is enabled by default
  • Connection pooling cannot be configured from my application
  • Default maximum pool size is 100
  • There is no way to change the maximum pool size unless the driver you are using supports it

Can someone confirm this, and/or suggest a method to limit the number of connections in this situation? Thank you very much :)

È stato utile?

Soluzione

You can try the WCF approach as mentioned or you could implement the connection pooling programmatically.

public interface IService
{
    void Execute(Action<IDbConnection> command);
    T Execute<T>(Func<IDbConnection, T> command);
}

public sealed class ConnectionManager : IService
{
    public const int MaxConnections = 10;

    private readonly string _connectionString;
    private readonly SemaphoreSlim _workers = new SemaphoreSlim(0, MaxConnections);

    public ConnectionManager(string connectionString)
    {
        _connectionString = connectionString;
    }

    public void Execute(Action<IDbConnection> command)
    {
        lock(_workers)
        {
            using(var connection = new OdbcConnection(_connectionString))
            {
                connection.Open();
                command(connection);
            }
        }
    }

    public T Execute<T>(Func<IDbConnection, T> command)
    {
        lock(_workers)
        {
            using(var connection = new OdbcConnection(_connectionString))
            {
                connection.Open();
                return command(connection);
            }
        }
    }
}

The SemaphoreSlim will prevent more than 10 connections from opening assuming the code that is called doesn't try anything sneaky.

Altri suggerimenti

You could consider configuring the WCF service to only allow 10 simultaneous requests. This will only work if each request uses no more than 1 db connection, of course, any may or may not make sense for your particular service.

Sounds to me like the architecture of your application should be reconsidered. I would deal with this situation by having a separate thread (or threads ) that connects to the database in your web service. The web service could then manage the thread(s) that connects to the database.

For simplicity assume only one connection to the database.

When you get a request for the web service the the service will put the request into the queue of the shared database thread.

The database thread will just sit there until there is something in the queue to process. When there is it will take it off the queue and send the request to the server.

It is likely that you will have a bit of extra work here in picking up the returned data too because the data will be returned on a different thread to the thread it was requested on.

The same principle could be used having multiple threads ( one per allowed connection ) You would then write a class to manage the threads so the each thread just took the next item from the queue.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top