Dailycode.info

Short solution for short problems

Combining self-tracking entities context with a Generic Singleton class. (Caching and/or refreshing)

This post is because I was using a generic singleton to instantiate the context of the entity framework. This resulted in a good chaching framework. All requests were enjoying this cached framework and passing changes to each other. But then some data was changed by an external application, even some data manipulated directly on the DB. The website did not reacht to these results, unless you would recycle the applicatin pool and release the generic singleton instance. So we came up wih a solution combining the strengt of this caching principle and still react to changes outside of the context.

We have several process layer classes in which we relate several data. For example for all master data I have a class MasterDataPL.cs: this class instantiates the context of the entity framework. Since its more or less static data, we can fully use the single instance. I also have a class with production data. The difference here is in the instantiating. Since this data changes a lot, I need to get a new instance of the context before every selection of data. The data can be manipulated from outside of the program, even directly in the database. To reflect these changes immediately, we cannot cache the data.

In the master data class, I will instantiate the context only once and use this instance as long as the process lasts:

private MyProjectEntities.Entities ents;

 

public MyProjectEntities.Entities StaticEnts

{

    get

    {

        if (ents == null)

        {

            ents = new MyProjectEntities.Entities(ConnectionString.ToString());

        }

        return ents;

    }

}

 

To get static data I just use the property accessor  StaticEnts. Also insert, update and delete actions will use this StaticEnts property.  Since this data is not manipulated from outside frequently (because the data is still refreshed after a recycle of the app pool).

Get data

public List<Users> GetAllUsers()

{

    return StaticEnts. Users.OrderBy(u => u.LastName).ThenBy(u => u.FirstName).ToList();

}

 

Update data

public void SaveProject(Projects project)

{

    try

    {

        project.Modified = DateTime.Now;

        StaticEnts.Projects.ApplyChanges(project);

        StaticEnts.SaveChanges();

    }

    catch (Exception er)

    {

        StaticEnts.Refresh(RefreshMode.StoreWins, project);

        throw new ArgumentException("Save failed, please check your data!", er.InnerException);

    }

}

 

Now, for the variable data, we still use the static property accessor for all insert, update and delete. But for the selection of data, we use a new instance of the context. Resulting in 2 properties, that we can use depending on the data:

private MyProjectEntities.Entities ents;

 

public MyProjectEntities.Entities Ents

{

    get

    {

        ents = new MyProjectEntities.Entities(ConnectionString.ToString());

        return ents;

    }

}

 

public MyProjectEntities.Entities StaticEnts

{

    get

    {

        if (ents == null)

        {

            ents = new MyProjectEntities.Entities(ConnectionString.ToString());

        }

        return ents;

    }

}

 

So to get data, it simply looks like this:

public ProjectDomains GetDomain(int domainID)

{

    return Ents.ProjectDomains.Where(pd => pd.DomainID == domainID).FirstOrDefault();

}

 

This will get the latest data from the database.  This way we minimalize the delays for getting data from and sending data to the database.

The caching now happens using the generic singleton pattern:

GenericSingleton<MYProjectsPL.ProjectsPL>.GetInstance().GetAllProjects(userID);