I need to provide access to a Key/Value pair store that persists for all users across session.
I could easily create a singleton for this, but for performance reasons I want to limit the size of the dictionary to 10000 items (or any performant number, as the object will persist indefinitely)
Is there a form of dictionary where I can specify a limit to the number of objects stored, and when that limit is exceeded, remove the oldest entry?
There is no such built-in dictionary, but you can build your own. You will need a queue for keys - that will allow you quickly find oldest entry and remove it. Also you will need a simple dictionary for keeping your values - that will allow you quickly search for them:
public class SuperDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> dictionary;
private Queue<TKey> keys;
private int capacity;
public SuperDictionary(int capacity)
{
this.keys = new Queue<TKey>(capacity);
this.capacity = capacity;
this.dictionary = new Dictionary<TKey, TValue>(capacity);
}
public void Add(TKey key, TValue value)
{
if (dictionary.Count == capacity)
{
var oldestKey = keys.Dequeue();
dictionary.Remove(oldestKey);
}
dictionary.Add(key, value);
keys.Enqueue(key);
}
public TValue this[TKey key]
{
get { return dictionary[key]; }
}
}
NOTE: You can implement IDictionary<TKey,TValue>
interface, to make this class a 'true' dictionary.
Use the Cache
, rather than Session
. It's not user specific, and you can set the maximum size of the cache. When new items are added and the cache is full, it'll remove items to make space. It allows for sophisticated aging mechanisms, such as items being removed after a fixed period of time, a fixed period of time after their last use, priorities (to be taken into consideration when deciding what to remove), etc.
No, there is no built-in dictionary that does this. In fact, all of the generic collections are infinite-sized.
However, you could easily make a Queue<KeyValuePair<string, int>>
and a function that checks the count and performs a dequeue when an element is added and the length is too long. Dictionary
is a difficult choice here because there is no way to determine "age" (unless you make it part of the key or value).
Something like:
public void AddDataToDictionary(string key, int value)
{
if (queue.Count > 10000)
queue.Dequeue();
queue.Enqueue(new KeyValuePair(key, value);
}
Here's a dictionary implementation that has the following removal strategies:
EmptyRemovalStrategy<TKey> – Removes the first item in it’s internal collection. Does not track access in any way.
MruRemovalStrategy<TKey> – Removes the most recently used (most accessed) item in the CacheDictionary.
LruRemovalStrategy<TKey> – Removes the least recently used (least accessed) item in the CacheDictionary.
The CacheDictionary is a dictionary with a limited number of items. So you'd be able to specify a max size of 1000. With this implementation you would also be able to determine the "age" of an entry and remove the least used (hence a cache)
http://alookonthecode.blogspot.com/2012/03/implementing-cachedictionarya.html