Robbie Mills Robbie Mills - 2 months ago 34
C# Question

Confused about static methods with Entity Framework

I'm calling the following from my controller:

public ViewResult Index()
{
var users = SecurityHelpers.GetAllStaff();
return View(users);
}


The method I'm calling to get all my users looks like this:

public class SecurityHelpers
{
private static Context db = new Context();

public static IQueryable<ApplicationUser> GetAllStaff()
{
var users = db.Users
.OrderBy(x => x.FirstName).ThenBy(x => x.LastName);
return users;
}
}


My problem is that when I modify a staff member, such as by setting a disabled boolean, the method is bring back their old data (so the disabled user is still enabled). I think this is because static functions are cached until the app pool recycles?

Is there a way to also get the latest data from this method without making it non-static? (as there is a lot of code that will need to be changed to instatiate the object each time, and I don't think that's the right architecture)

Answer

I think this is because static functions are cached until the app pool recycles

No. The problem is that you use a long-lived context (db) that you keep alive forever in a static variable, and this context is caching all the entities you are querying.

There is a way to refresh the cached entities so that you don't get stale values, but the real problem here is that you really shouldn't be keeping a long-lived context like that. It comes with this problem of stale data, and as the cache grows, you will also start noticing bad performance.

Notice what the documentation says about how entities are returned from queries (emphasis mine):

When results are returned from the database, objects that do not exist in the context are attached to the context. If an object is already in the context, the existing object is returned

One viable alternative is to create the context as needed. Example:

public class SecurityHelpers
{
    public static IList<ApplicationUser> GetAllStaff()
    {            
        using(var db = new Context())
        {
            var users = db.Users
                    .OrderBy(x => x.FirstName).ThenBy(x => x.LastName)
                    .ToList();            
            return users;
        }
    }
}

Depending on how your application is architected, you may be able to set it up so that you have a context instance per request instead. That would be even better IMO. However you decide to do it, don't use a singleton context!