1

First, a link to the library: ServiceStack.Redis

Now, I want to store objects of type T where T contains fields Key and Value. (for this example)

The issue is that it seems like I can only store strings as both keys and values. As far as a string key, thats perfectly fine, but I need to store an object as the value.

Attached is my code which supports to map Hash -> KeyValuePair items

public void PutDictionary(string hashKey, Dictionary<string, T> items, TimeSpan expiration)
{
    try
    {
        using (var trans = _client.CreateTransaction())
        {
            foreach (KeyValuePair<string, T> item in items)
            {
                trans.QueueCommand(r => r.SetEntryInHash(hashKey, item.Key, ???));
            }

            trans.Commit();
        }
    }
    catch (Exception e)
    {
        // some logic here..
    }
}

Im aware that I can just JSON stringify my objects but it seems like this just consumes a very much needed performance and losing the effect of good-fast cache memory.

Ill explain what I want to achieve. Lets say I have a group and peoples in it. The group has an Id and each entity inside this group also has an Id. I want to be able to get a specific person from a specific group.

In C# its equivilant of doing Dictionary<string, Dictionary<string, T>>

Ori Refael
  • 2,888
  • 3
  • 37
  • 68

1 Answers1

2

You should just serialize the value object as a string. There's no concept of storing objects in Redis, when ServiceStack.Redis offers a Typed API with it's Typed Redis Client it's just serializing the object behind the scenes to JSON and sending the JSON string to Redis.

ServiceStack.Redis also provides APIs like StoreAsHash(T) and SetRangeInHash where the objects properties are stored in a Redis Hash, however in this case you're storing a nested Hash so the value can't be another Redis Hash.

You could allow another "nested Dictionary" by saving the object at a custom key that combines hashKey with the Dictionary key, e.g:

foreach (var entry in items) {
    var cacheKey = hashKey + ":" + entry.Key;
    var mapValues = entry.Value.ToJson()
        .FromJson<Dictionary<string,string>>();
    redis.SetRangeInHash(cacheKey, mapValues);
}
mythz
  • 141,670
  • 29
  • 246
  • 390
  • can you explain what your 2nd row does? it takes the value, convert it to string and does what? Is what you wrote adds keys or just overriding the entire hash? – Ori Refael May 16 '17 at 11:28
  • @OriRefael it converts it into a string Dictionary – mythz May 16 '17 at 11:39
  • yeah, i blacked out totally...thanks alot. also, a bonus if you may, is there a way to set the expiration of the set in the same request? i mean, i haven't tried it yet, but im sure i have to use transaction here – Ori Refael May 16 '17 at 11:40
  • @OriRefael no Redis doesn't allow setting expiration within the same hash request, you'll need to expire the key after. – mythz May 16 '17 at 11:41
  • even if i use transaction for this? – Ori Refael May 16 '17 at 11:42
  • @OriRefael could but don't see the point just for setting an expiration, the end result is the same – mythz May 16 '17 at 11:44
  • because if i wont do that, my cache is gonna stay there forever (or till the maitenance window..still learning about AWS ElastiCache), also, I will have irrelevant data after a while – Ori Refael May 16 '17 at 11:45
  • @OriRefael I mean, just set the expiry on the key in the next command using `ExpireEntryIn()` or `ExpireEntryAt()`, no need to wrap it in a transaction. – mythz May 16 '17 at 11:54