Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard way of implementing a proprietary connection pool in .net?

Tags:

c#

.net

api

pooling

Is there a standard connection pooling model (or API) similar to that used by the data providers in .net that I could use to implement my own connection pool?

I ask because I have a requirement to implement my own connection pool to a proprietary TCP/IP device that we use in a web service. The current problem is that there are lot of connections (read too many) to the device due to the threaded nature of web services running under IIS. I want to limit the number of these connections using my own connection pool and it seems stupid to reinvent the wheel if there is a standard model I could use to do this.

like image 891
VinceJS Avatar asked Jul 18 '09 20:07

VinceJS


2 Answers

Is there a standard connection pooling model

Other than ADO.NET, no. But the ADO.NET model is nice an simple. Construct an object to get a connection from the pool, or created anew, and it is returned to the pool on Close/Dispose/Finalise.

From this one can immediately determine an implementation pattern:

  • The client type is a proxy to the real type, and has a lifetime from creation to Close/…. It is a proxy to the real object. Provides methods and properties which forward to the real connection.
  • The real connection is a long lived instance, created by the pool, given out under a proxy and then returned at the end of the proxy.

There is a choice in the implementation. When an object has been handed out, does the pool need to also keep a reference? If it does the pool needs to track which objects are active and which are pooled; otherwise a simple collection of available objects can be used.

Something like:

internal class MyObjectImpl {
  // The real object that holds the resource
}

internal static class MyObjectPool {
  private static object syncRoot = new object();
  private static Queue<MyObjectImpl> pool = new Queue<MyObject>();
  private static int totalObjects = 0;
  private readonly int maxObjects = 10;

  internal MyObjectImplGet() {
    lock (syncRoot) {
      if (pool.Count > 0) {
        return pool.Dequeue();
      }
      if (totalObjects >= maxObjects) {
        throw new PoolException("No objects available");
      }
      var o = new MyObjectImpl();
      totalObjects++;
      return o;
    }
  }

  internal void Return(MyObjectImpl obj) {
    lock (syncRoot) {
      pool.Enqueue(obj);
    }
  }
}

public class MyObject : IDisposable {
  private MyObjectImpl impl;

  public MyObject() {
    impl = MyObjectPool.Get();
  }

  public void Close() {
    Dispose();
  }

  public void Dispose() {
    MyIObjectPool.Return(impl);
    // Prevent continuing use, as the implementation object instance
    // could now be given out.
    impl = null;
  }

  // Forward API to implement

}

This doesn't cater for instances of MyObject being destroyed. E.g. hold a collection of weak references to allocated MyObject's, and if the pool is empty check for disposed instances. This would also be needed if you cannot rely on client's to Close or dispose of instances, or implement a finaliser on MyObjectImpl1 (and report this as an error in debug builds).

1 This cannot be done on MyObject because by the time MyObject was finalised the MyObjectImpl instance could already have been finalised.

like image 143
Richard Avatar answered Oct 21 '22 12:10

Richard


Update

Actually now I know more, I think I'd use a feature from my IoC container of choice - Castle Windsor. One of the built-in lifestyles is "pooled", which means that whenever you ask the container for an object that was registered with this lifestyle, it'll give you one of the pooled objects if it can, or else create a new one.

Previously...

I think you want to implement "object pooling". Here's a few things that looked promising:

  • http://www.codeproject.com/KB/mcpp/objectpooling1.aspx
  • http://www.codeproject.com/KB/recipes/ObjectPooling.aspx

Of course with your pooled objects, you need to be careful with concurrency and thread synchronisation etc.


For database connections:

You can control the number of connections in the .NET connection pool with an option in the connection string: "max pool size" as described in: http://msdn.microsoft.com/en-us/library/8xx3tyca(VS.71).aspx

Try to avoid implementing your own if you can.

like image 40
Neil Barnwell Avatar answered Oct 21 '22 14:10

Neil Barnwell