2

What are the solutions for data persistance in a .NET webservice?

I have a webservice. I give an id to my webservice and this one return the correct objet.

        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "/GetMyObject?id={id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        MyObject GetMyObject(string id);

I don't want to use a database. I would like to keep my collection of objects in "memory". So I decided to create a simple object in my webservice like this

    public class Service : IService
    {
        List<MyObject> list = new List<MyObjec>();

        public Service()
        {
            list.Add(new MyObject() { Id = 1, Data = ...} );
            list.Add(new MyObject() { Id = 2, Data = ...} );
            list.Add(new MyObject() { Id = 3, Data = ...} );
            list.Add(new MyObject() { Id = 4, Data = ...} )
            ...
        }

        public MyObject GetMyObject(string id)
        {
            // code to get my object from the list
            return myObject;
        }
}

It works but the constructor is called each times I call my webservice and I would like to initialize this list once and apply modification on it later. How should I initialize my list and persists it?

Bastien Vandamme
  • 17,659
  • 30
  • 118
  • 200
  • At this moment I don't mind about concurency but yes in a final solution I ll have to use something else than a list. – Bastien Vandamme Jun 27 '12 at 16:42
  • I am not sure of the definition of data persistence in Web Services. Would you require data to be persistent if you had to reboot the Service and the Server, clearing all memory? – The Original Android Jun 27 '12 at 16:48

3 Answers3

8

You could use a static collection:

private static List<MyObject> list = new List<MyObjec>();

and of course since this is a multithreaded application where potentially you could have concurrent access to this collection, you must ensure to synchronize the access to it. Or if you are using .NET 4.0 simply use a thread safe ConcurrentBag<T>:

private static ConcurrentBag<MyObject> list = new ConcurrentBag<MyObjec>();

Of course you should perfectly fine be aware that by using an in-memory structure to store your data your data life is basically tied to the life of the web application. And since IIS could recycle the application domain at any moment (a certain period of inactivity, certain CPU/memory thresholds are reached) everything you have stored into memory goes into the void.

By the way if you go that route, be prepared this to happen very often, every time you recompile your web service, because by recompiling you are basically modifying the assemblies in the bin folder and the web server will simply recycle the application.

So yeah, all this wall of text to tell you to persist your data somewhere else than in-memory :-) You've got so many possibilities ranging from files in different formats, databases, embedded databases, ...

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • And how can I initilize my list once when I start my webservice project ? – Bastien Vandamme Jun 27 '12 at 16:40
  • 1
    You could use a [static constructor](http://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx) for the web service class which is guaranteed by the CLR to be invoked only once per AppDomain lifetime. – Darin Dimitrov Jun 27 '12 at 16:41
3

Alternatively, you can make your service a singleton

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                 ConcurrencyMode = ConcurrencyMode.Single)]
class Service
...

However, this approach leads to huge problems in future. Do not store anything in-memory. If you do, you embed a state into the application. This leads to tremendous amount of work needed to achieve high reliability and scalability. No state, no pain.

oleksii
  • 35,458
  • 16
  • 93
  • 163
  • If you do this, you should no longer use `List` because if you have 2 concurrent calls of the web method you will get corrupt data. – Darin Dimitrov Jun 27 '12 at 16:40
  • @oleksii Is this solution performant for a webservice that will be call all the time? each milisecond by many computers? – Bastien Vandamme Jun 27 '12 at 16:43
  • @DarinDimitrov yes you are right, I added `ConcurrencyMode.Single` for this. Alternatively, Dran can use `ConcurrantBag` following your answer. – oleksii Jun 27 '12 at 16:53
  • @DranDane this solutions is for a quick test. I would not use it in high-performant applications. – oleksii Jun 27 '12 at 16:55
0

WCF has built in instance management.

Vano Maisuradze
  • 5,829
  • 6
  • 45
  • 73