Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global vs Singleton in .NET

I have a very common situation here. And for years I haven't found if what i am doing is RIGHT by industry standards.Consider an application which connects to the database, but where the connection string instead of being stored in some file/setting is being passed as a command line parameter at startup OR the database is browsed to at the time the application starts up.

Well it becomes necessary to save that connection string somewhere within the scope of the app. Most common way I have seen it done is a module or global class with get/set methods to save the connections string. Another way I would do it is using Singleton. Either options my DAL can access the connection string when it needs to through a GetConnectionString method.

Is there a BETTER way of doing this?

Update: i do not have a config file and even if I did I would need the connection string to be read once for the life of the application instance. can you elaborate on the "inject it into any classes" part

like image 650
user52960 Avatar asked Feb 02 '09 17:02

user52960


2 Answers

In general global state, be it a global class or a singleton, should be avoided wherever possible.

The ideal solution would be to have your application load up the connection string out of config and inject it into any classes that need it. Depending on the size of your application, an IoC container like Unity or Castle Windsor can help, but certainly isn't a required part of the solution.

If that isn't an option and you're stuck maintaining global state (because of the existing codebase or whatever), I don't know that there's a huge difference between the two approaches you've suggested.

Update: Just to clarify, forget all the stuff about IoC containers for now, "Inject" is just a fancy way of saying "pass in as a parameter" (either to the class's constructor, or via a property, or whatever).

Rather than having a data access class have to ask for the connection string (from some sort of global or a singleton), have it passed in via the constructor or a property.

Update #2: I think there's still some misunderstanding as to what this approach entails.

It basically comes down to whether your data access class looks like:

public class DataAccessClass
{
    public DataAccessClass()
    {
        _connString = SomeStaticThing.GetConnectionString();
    }
}

or

public class DataAccessClass
{
    public DataAccessClass(string connString)
    {
        _connString = connString;
    }
}

These articles (and in fact, many of the articles in that blog) detail a number of reasons why the latter is better than the former (not least because the former is almost impossible to unit test).

Yes, at some place there is going to have to be some static guy responsible for grabbing the connection string in the first place, but the point is that your dependencies on static methods are limited to that one spot (which is likely going to be your Main method in the process of bootstrapping your application), rather than sprinkled throughout your whole codebase.

like image 53
AwesomeTown Avatar answered Oct 04 '22 05:10

AwesomeTown


it's nice to see so many creative solutions to such a simple problem ;-)

salient facts, from OP question:

  1. the connect-string is passed on the command-line
  2. many other components may need to use the connect-string

so, there is no way around the use of a static element; whether it's a global variable (hard to do in .NET, really, without an enclosing class), a static class, or a singleton really doesn't matter. The shortest-path solution would be a static class initialized by the Program class that processed the command-line.

Every other solution would still require static access to the passed-in connect-string, though they may hide this behind one or more layers of indirection.

I'm not saying that you don't want to dress up the basic solution with something fancier, but it is not necessary, and it does not eliminate the fundamentally static/global nature of the connect-string as described.

like image 26
Steven A. Lowe Avatar answered Oct 04 '22 03:10

Steven A. Lowe