1

Is it possible to allocate a persistent object, a List or a Dictionary, for example in the context of a .NET WCF Service? In other words, is there a way to access the result of previous calls to such a service, other than storing the results in an SQL database? Please provide a reference or an explanation.

Aharon Manne
  • 712
  • 3
  • 11
  • 34

1 Answers1

0

Yes, it's possible with (but not only) sessions. Explanation is pretty long to refer to this CodeProject article for more details. Please note that they're not same thing as ASP.NET sessions, they're useful to link multiple calls together (for example to manage a transaction) but it can be easily used to store data.

Here just a very short introduction as a quick reference. To configure sessions in WCF you should setup the following three elements: Binding, SessionMode and InstanceContextMode.

Not all protocols allows every kind of sessions so for example:

<endpoint address="a" binding="wsHttpBinding" 
          contract="WcfTest.IService" name="b"/>

Decorate your contract with SessionMode:

[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface IService {
}

And your implementation with InstanceContextMode:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Serviceclass : IService {
}

What you have now is a specific instance of your service per each client connection. There are, of course, disadvantages and drawbacks. What comes to my mind first:

  • Memory usage on server will increase (not only memory but many resources in general) because state is kept on memory and sessions must be tracked.
  • Load balancing will be much harder to do (because you have to track sessions) and you may finish to use a layer 7 l.b. to do not make your application too complex because of sessions. In contrast a database based solution will scale well on a layer 4 load balancing too.

Of course there are alternatives. Just a quick list:

  • As you thought you can store session data in a database.
  • You can store session data in a token you send to client and you ask back for each call. When client negotiate a connection you send him an opaque token (may even be a simple dictionary) and it has to send it back to each request (as parameter of each contract method).
  • You can build a session data repository, anoteher private WCF service that keep track of session data. This service won't scale well for load balancing but your service will. You can store data in it with a simple MemoryCache object.
  • You can setup an ASP.NET style cache. Topic is pretty long so please refer to this nice post here on SO.

A note about static fields: they live in ApplicationDomain so they're shared across all instances (when InstanceContextMode is not PerSession). It may work as cache (for examle using a raw dictionary) but you have to manage object lifetime (static members will be destroyed when server or host process restarts). To use them you shouldn't use sessions and you have to manage synchronization too (because each request may be served in a different thread so static fields will be accessed concurrently). If load balancing isn't an issue for you then you may consider to use a static shared MemoryCache (it's thread safe but you still have to manage objects lifetime by your own).

Community
  • 1
  • 1
Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Thanks @Adriano. Without having added the decorations you specified, I defined my dictionary as static, and it seems to be persistent within the debugging session. Why does this seem to work, and would it work when deployed on an actual server? – Aharon Manne Jan 20 '14 at 10:58
  • @AharonManne they work because static fields are shared across all sessions (it means that two clients will see that dictionary, and may share data). Besides synchronization problems and assuming you're using a cache object like MemoryCache you still have the problem of load balancing. That said they works unchanged in a true server too. BTW do not forget they lives until server is restarted so data won't be dropped when a client finishes with your service. – Adriano Repetti Jan 20 '14 at 11:04