views:

1640

answers:

6

I have created a Registry class in .NET which is a singleton. Apparently this singleton behaves as if it were kept in the Cache (the singleton object is available to each session). Is this a good practice of should I add this Singleton to the Cache? + do I need to wacth out for concurrency problems with the GetInstance() function?

namespace Edu3.Business.Registry
{
    public class ExamDTORegistry
    {
        private static ExamDTORegistry instance;
        private Dictionary<int, ExamDTO> examDTODictionary;

        private ExamDTORegistry()
        {
            examDTODictionary = new Dictionary<int, ExamDTO>();
        }

        public static ExamDTORegistry GetInstance()
        {
            if (instance == null)
            {
                instance = new ExamDTORegistry();
            }
            return instance;
        }
    }
}
+2  A: 

Well, your GetInstance method certainly isn't thread-safe - if two threads call it at the same time, they may well end up with two different instances. I have a page on implementing the singleton pattern, if that helps.

Does your code rely on it being a singleton? Bear in mind that if the AppDomain is reloaded, you'll get a new instance anyway.

I don't really see there being much benefit in putting the object in the cache though. Is there anything you're thinking of in particular?

Jon Skeet
Yeps, when AppDomain is reloaded, the a new instance is no problem. But a singleton does behave like a global object, no? When testing I can see that ASP.NET doesn't create a singleton for each session, but just a singleton for the whole application.
Lieven Cardoen
+3  A: 

Despite their presence in GoF singletons are generally considered bad practice. Is there any reason why you wish to have only one instance?

It's a good practice when used in the right place. Unfortunately I've NEVER worked in a place that really *needed* one, though I've seen them implemented hundreds of times :)MonoState is a good alternative.
Ben Scheirman
Indeed, and discussions on this by the hundred on the internet...
Lieven Cardoen
To answer your question, well, I have 200 candidates all requesting the same ExamDTO (by id) at the same time. I saw that server side code went 200 times to the database to get the Exam. Now I wanted to cache an Exam by its id, so that when already loaded, the server wouldn't go to the db again.
Lieven Cardoen
Then you want a cache (not a singleton it's dangerous to confuse the two). For one suggestion see Ben's comment on MonoState. Otherwise hide the caching in your datalayer. Good O/R mappers like NHibernate support this sort of thing already.
Another question (sorry to pry): is this causing you a performance issue? You'd be surprised but 200 requests for the same record is a breeze for most modern dbs.If you are having a perf issue I completely understand the need for a cache.
I'll be honest with you, I'm a senior flexer trying to learn ASP.NET now already for one year and a half. It's actually 200 requests to a stored procedure that's quite intensive. If I were to do it with NHibernate or SubSonic a single request would need to adress a couple of records.
Lieven Cardoen
What's the difference between a cache and a singleton? The behavior looks the same... The Singleton can be called from within any session (it'sl like a global variable).
Lieven Cardoen
I've looked at MonoState and isn't Singleton a sort of MonoState with one Static variable, the instance itself?
Lieven Cardoen
Singleton is for restricting a class to only one instance with global access.The monostate pattern is a way of multiple instances having shared state.A cache provides access to the same object multiple times without creating new instances of them.MonoState is ONE way of implementing a cache.
"The Singleton can be called from within any session (it'sl like a global variable)" And global variables are BAD and are NOT a correct use of the singleton pattern.
A: 

Not sure sure what you mean by cache... if you want this cached (as in... keep it in memory so that you don't have to fetch it again from some data store) then yes, you can put it in the cache and it will be global for all users. Session means per user, so I don't think this is what you want.

Ben Scheirman
A: 

I'd also like to know the answer to this... I have several applications that store domain tables into static list objects: I could never find a reason why it would be beneficial to add these to the cache (unless I suppose you had some cache implementation that wasn't in memory?)

John
A: 

HttpContext.Cache is available to all sessions, but items in the cache can be removed from memory when they expire or if there is memory pressure.

HttpContext.Application is also available to all sessions and is a nice place to store persistent, application-wide objects.

Since you've already created a singleton and it works, I don't see why should use one of the ones built-in singleton collections instead, unless you need the extra functionality that Cache gives you.

Greg
What is that extra functionality?
Lieven Cardoen
Expiring/removing items from memory.
Greg
A: 

i would make it like:

private static READONLY ExamDTORegistry instance;

then you dont need to check for NULL and its thread safe.