Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with singleton pattern inside WCF service method

I will go ahead and preface this by saying: I am somewhat new to WCF.

I'm working on a server-side routine that's responsible for doing a great deal of business logic. It's accessible from a client via WCF.

My main WCF method calls off to several other private methods. Instead of passing around all of the "lookup data" I need for the business logic to each private method, I decided to use a singleton instance of a class named DataProvider that contains all of this "lookup data".

At the end of the routine, I "release" the DataProvider's lookup data so the next time the routine is executed, the latest lookup data will be used.

So, here's a simplified example:

 public void Generate()
 {
      try
      {
           //populate singleton DataProvider with it's lookup data...
           DataProvider.Instance.LoadLookupData();

           //do business logic...
      }
      finally
      {
           //release provider's lookup data...
           DataProvider.Release();
      }
 }

This works great until I have two different clients that execute the method at (or near) the same time. Problems occur because they share the same singleton instance and the task who finishes first will release the DataProvider before the other completes.

So...

What are my options here?

I'd like to avoid passing around all of the lookup data so the singleton pattern (or some derivative) seems like a good choice. I also need to be able to support multiple clients calling the method at the same time.

I believe the WCF service is configured as "Per-Call". I'm not sure if there's a way to configure a WCF service so that the static memory is not shared between service invocations.

Any help would be appreciated.

like image 405
John Russell Avatar asked Aug 01 '11 12:08

John Russell


People also ask

What is the problem that singleton pattern solves?

More specifically, the singleton pattern allows objects to: Ensure they only have one instance. Provide easy access to that instance. Control their instantiation (for example, hiding the constructors of a class)

What are the disadvantages of singleton pattern?

Singletons hinder unit testing: A Singleton might cause issues for writing testable code if the object and the methods associated with it are so tightly coupled that it becomes impossible to test without writing a fully-functional class dedicated to the Singleton.

Should WCF client be Singleton?

Specifically, if you need to centralize business logic [more applicable in a standalone application than a remote WCF service], or share memory or a resource, a Singleton works well. Of course, if you are sharing business logic, state is maintained in the call stack, and multi threading is moot.

What are the consequences of applying the singleton pattern?

Some consequences of the Singleton pattern include controlling access, permitting subclassing, and enhancing flexibility.


1 Answers

By default WCF is using "Per-Call", which means new instance of the WCF service is created for each client's call. Now since you implemented singleton even though new instance of the WCF is created it still calls your singleton.

If you would like to create lookup that is created for each call (like you have now) you should not do it as singleton. This way each client that calls your method will have new instance of the lookup, I think that was your intention.

However if you have lookup that is not changing that fast, I would recommend to share it between all calls, this will improve performance of your WCF service. You will need to declare your WCF service as

InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple  

What this does is creating Singleton automatically for you by WCF, so you don't have to do it yourself, second it will support > 1 concurrent user (ConcurrencyMode.Multiple).

Now if you have your lookup that is changing and it needs to be reloaded after some period of time, I still would recommend using

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple

but inside in your code cache it and then expire your cache at specific time or relative time (1 hours).

Here are some links that might help you: 3 ways to do WCF instance management (Per call, Per session and Single)

Hope this will help.

like image 135
Vlad Bezden Avatar answered Oct 29 '22 07:10

Vlad Bezden