realtek
realtek

Reputation: 841

Storing global variables in c#?

I basically have created a class which when a user logs into a website it then queries the database and stores some settings in a List (So I have key/pair values).

The reason for this is because I want to always be able to access these settings without going to the database again.

I put these in a class and loop through the fields via a SQL query and add them to the list.

How can I then access these variables from another part of the application? or is there a better way to do this? I'm talking server side and not really client side.

Here is an example of what I had at the moment:

public static void createSystemMetaData()
{
    string constring = ConfigurationManager.ConnectionStrings["Test"].ConnectionString;
    SqlConnection sql = new SqlConnection(constring);
    sql.Open();

    SqlCommand systemMetaData = new SqlCommand("SELECT * FROM SD_TABLES", sql);
    //Set Modules
    using (SqlDataReader systemMetaDataReader = systemMetaData.ExecuteReader())
    {
        while (systemMetaDataReader.Read())
        {
            var name = systemMetaDataReader.GetOrdinal("Sequence").ToString();
            var value = systemMetaDataReader.GetOrdinal("Property").ToString();
            var Modules = new List<KeyValuePair<string, string>>();
            Modules.Add(new KeyValuePair<string, string>(name, value));
        }
    }
}

Thanks

Upvotes: 1

Views: 1764

Answers (4)

Bob Vale
Bob Vale

Reputation: 18474

From the looks of things you are using universal values irrespective of users so an SqlCacheDependency would be useful here:

Make sure you setup a database dependency in web.config for the name Test

public static class CacheData {

  public static List<KeyValuePair<string,string>> GetData() {
    var cache = System.Web.HttpContext.Current.Cache;
    SqlCacheDependency SqlDep = null; 
    var modules = Cache["Modules"] as List<KeyValuePair<string,string>>;
    if (modules == null) { 

        // Because of possible exceptions thrown when this 
        // code runs, use Try...Catch...Finally syntax. 
        try { 
            // Instantiate SqlDep using the SqlCacheDependency constructor. 
            SqlDep = new SqlCacheDependency("Test", "SD_TABLES"); 
        } 

        // Handle the DatabaseNotEnabledForNotificationException with 
        // a call to the SqlCacheDependencyAdmin.EnableNotifications method. 
        catch (DatabaseNotEnabledForNotificationException exDBDis) { 
                SqlCacheDependencyAdmin.EnableNotifications("Test"); 
        } 

        // Handle the TableNotEnabledForNotificationException with 
        // a call to the SqlCacheDependencyAdmin.EnableTableForNotifications method. 
        catch (TableNotEnabledForNotificationException exTabDis) { 
                SqlCacheDependencyAdmin.EnableTableForNotifications("Test", "SD_TABLES"); 

       } 
       finally { 
            // Assign a value to modules here before calling the next line
            Cache.Insert("Modules", modules, SqlDep); 
        } 
      }
      return modules;
    }

Upvotes: 0

David Arno
David Arno

Reputation: 43254

As others have pointed out, the risk of holding these values in global memory is that the values might change. Also, global variables are a bad design decision as you can end up with various parts of your application reading and writing to these values, which makes debugging problems harder than it need be.

A commonly adopted solution is to wrap your database access inside a facade class. This class can then cache the values if you wish to avoid hitting the database for each request. In addition, as changes are routed through the facade too, it knows when the data has changed and can empty its cache (forcing a database re-read) when this occurs. As an added bonus, it becomes possible to mock the facade in order to test code without touching the database (database access is notoriously difficult to unit test).

Upvotes: 0

m5c
m5c

Reputation: 567

For less users you can go with the SessionState as Bob suggested,however with more users you might need to move to a state server or load it from Data Base each time.

Upvotes: 0

pattermeister
pattermeister

Reputation: 3232

Any static properties of a class will be preserved for the lifetime of the application pool, assuming you're using ASP.NET under IIS.

So a very simple class might look like:

public static class MyConfigClass
{
    public static Lazy<Something> MyConfig = new Lazy<Something>(() => GetSomethings());

    public static Something GetSomethings()
    {
        // this will only be called once in your web application
    }
}

You can then consume this by simply calling

MyConfigClass.MyConfig.Value

Upvotes: 2

Related Questions