Reputation: 1037
I have a class which does caching in the service layer business objects of my web app. When the code runs on a load-balanced server, when a client hits one machine and updates their details, but then close the browser, reopen it and happen to hit the website on one of the other machines on the load-balanced solution, their latest changes are not visible.
This basic class is inherited by my other business objects like the People. Is there a way I can refresh this cached object on the other servers on the load-balanced environment, so the client always sees the latest?
public abstract class CacheStore<T> where T:IComparable, new()
{
private class CacheItem
{
public T Item
{
get;
set;
}
public DateTime Expires
{
get;
set;
}
}
private List<CacheItem> theCache = new List<CacheItem>();
public abstract TimeSpan Lifetime
{
get;
}
public int CountAll
{
get
{
return theCache.Count();
}
}
public int CountExpired
{
get
{
return theCache.Count(i => i.Expires < DateTime.Now);
}
}
public void Add(T item)
{
CacheItem i = (from c in theCache where (c.Item.CompareTo(item) == 0) select c).FirstOrDefault();
if (i != null)
{
if (i.Expires < DateTime.Now)
{
theCache.Remove(i);
i = null;
}
}
if (i == null)
{
theCache.Add(new CacheItem()
{
Expires = DateTime.Now + Lifetime,
Item = item
});
}
}
public IEnumerable<T> Filter(Func<T, bool> predicate)
{
return (from c in theCache where c.Expires > DateTime.Now select c.Item).Where(predicate);
}
public void MarkAsExpired(Func<T, bool> predicate)
{
var markAsExpired = from c in theCache
where this.Filter(predicate).Contains(c.Item)
select c;
foreach (CacheItem ci in markAsExpired)
{
ci.Expires = DateTime.Now.Subtract(TimeSpan.FromSeconds(1));
}
}
}
}
Upvotes: 0
Views: 5191
Reputation: 4232
Lloyd's answer basically covers it.
It's a little unusual to roll your own cache in a .NET application. Generally you would use the caching built into the framework - see ASP.NET Caching for an overview, and the System.Web.Caching namespace. If you were doing that, you could for instance invalidate cached data on database changes using SqlCacheDependency.
For load-balanced environments, though, you would probably be better with a centralized cache as Lloyd recommended. If you want to stay with a Microsoft solution, AppFabric would be your go-to option.
Upvotes: 1
Reputation: 29668
This is to be expected as you're creating the cache within the local app domain that's scoped to the immediate server. Any objects created there are only relevant to that app domain.
To get around this you need to centralize the caching solution to a common server or using something like Couchbase/Memcached so that all servers can share the same cache.
Upvotes: 1