Recently I was working on implementing a small snippet that caches my results and the way I was doing it was using a Dictionary as follows:
private Dictionary<ID, IQueryable<Results>> _simpleCache;
The idea was to search for all the results that have the id specified by ‘ID’ and if the Dictionary contains the key == id, we simply search through the values present in the IQueryable instead of making a database trip.
I was going over this piece of logic this morning and I was thinking about replacing the IQueryable with HashSet as follows:
private Dictionary<ID, HashSet<Results>> _simpleCache;
Is making this change advisable?
Yes, it is. Generally,
IQueryable<T>implies that you are using a data source provider which is queried each time the queryable is enumerated (of course, this isn’t always the case, as you can call AsQueryable extension method on anIEnumerable<T>which will give you anIQueryable<T>implementation over theIEnumerable<T>implementation).To that end, storing the
IQueryable<Results>in a dictionary doesn’t actually prevent any hits to the data source when you enumerate through it a second time. It will make a request to the data provider every time you enumerate through it.Because of this, you typically want to materialize the results on the client side, usually calling the
ToListorToArrayextension methods, and then usingIEnumerable<Results>orResults[]as theTValuetype parameter of your dictionary.Note that you could use a
HashSet<T>to store your objects, but you have to make sure that you implementIEquatable<T>and overrideGetHashCodeso that the default equality comparer will perform a comparison on theIDinstance exposed by theResultstype, either that, or you have to provide anIEqualityComparer<T>implementation that will do the same thing. It’s more than likely that you are using designer-generated code, and it will not do this for you, and your objects will have equality determined by reference, not by value.