The proper solution is to have a Dictionary<TKey1, TKey2, TValue>, where 2 keys are needed to access a certain item. Solutions using Dictionary<TKey, List<TValue>> will create as many lists as there are unique values for TKey, which takes a lot of memory and slows down the performance. The other problem when having only 1 key is that it becomes difficult to remove one particular item.
Since I couldn't find such a class, I wrote one myself:
public class SortedBucketCollectionClass<TKey1, TKey2, TValue>:
IEnumerable<TValue>, ICollection<TValue>,
IReadOnlySortedBucketCollection<TKey1, TKey2, TValue>
where TKey1 : notnull, IComparable<TKey1>
where TKey2 : notnull, IComparable<TKey2>
where TValue : class {...}
It supports access with only TKey1, which returns an enumerator over all items having TKey1 and access with TKey1, TKEy2, which returns a particular item. There are also enumerators over all stored items and one that enumerates all items with a certain range of TKey. This is convenient, when TKey1 is DateTime and one wants all items from a certain week, month or year.
I wrote a detailed article on CodeProject with code samples:
SortedBucketCollection: A memory efficient SortedList accepting multiple items with the same key
You can get the source code on CodeProject or Github:
StorageLib/StorageLib/SortedBucketCollection.cs