Updating the Redis List Services List

Is there a correct way to update an IRedisList? With the code example below, I can modify it to delete the list, refresh the pizza and re-add the list, but this is wrong. The documentation on the command line is pretty simple, but it's a much larger project than me, and I'm not quite sure where to start.

public void UpdatePizza(Pizza pizza) { using (var redisClient = new RedisClient(Host, Port)) { IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>(); IRedisList<Pizza> pizzas = redis.Lists["pizzas:live"]; var toUpdate = pizzas.First(x => x.Id == pizza.Id); toUpdate.State = pizza.State; //??How to save } } 
+7
c # servicestack redis
source share
1 answer

Avoid listings:

Unfortunately, in this situation, Redis lists are not a good choice . I had the same problem when I started using Redis, they seem like an obvious choice;). Redis lists are useful if you use them as read-only, or just want to pop and click, but not to change an item in the middle of the list.

You can β€œupdate” items in a Redis list if you know the index of the element, but it needs to be deleted and reinserted, and it must be an index whose definition is terribly inefficient. He does this by iterating through the collection, because there is no own way to do this, and this is not a good idea. This is a snippet of the IndexOf RedisClientList<T> method.

 public int IndexOf(T item) { //TODO: replace with native implementation when exists var i = 0; foreach (var existingItem in this) { if (Equals(existingItem, item)) return i; i++; } return -1; } 

So, to complete your code, this would be:

 public void UpdatePizza(Pizza pizza) { using (var redisClient = new RedisClient(Host, Port)) { IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>(); IRedisList<Pizza> pizzas = redis.Lists["pizzas:live"]; var toUpdate = pizzas.First(x => x.Id == pizza.Id); toUpdate.State = pizza.State; // Update by removing & inserting (don't do it!) var index = pizzas.IndexOf(toUpdate); pizzas.Remove(index); pizzas.Insert(index, toUpdate); } } 

But this is not a good way to handle this, as I said. It will retrieve a list of other pizza objects and then iterate over them until it matches the index. And two update operations! :( It is better to avoid lists in this situation.

Decision:

As you try to access pizza by this identifier, you can create a unique pizza key for each object, this will allow you to directly access pizza. Therefore, we can use:

 pizzas:live:{Id} 

Examples:

Create pizza

 using (var redisClient = new RedisClient()) { IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>(); var pizzaKey = string.Format("pizzas:live:{0}", 123); var pizza = new Pizza { Id = 123, Type = "Mushroom", State = "Cooking" }; redis.SetEntry(pizzaKey, pizza); } 

Get Pizza From Id

 using (var redisClient = new RedisClient()) { IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>(); var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id); var pizza = redis.GetValue(pizzaKey); } 

Update pizza by id (just GET and SET)

 using (var redisClient = new RedisClient()) { IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>(); var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id); var pizza = redis.GetValue(pizzaKey); // Get pizza.State = "Delivery"; // Update redis.SetEntry(pizzaKey, pizza); // Save } 

Move to another "list" (possibly: when the state of pizza changes)

 using (var redisClient = new RedisClient()) { var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id); var deliveredKey = string.Format("pizzas:delivered:{0}", pizza.Id); redisClient.RenameKey(pizzaKey, deliveredKey); } 

Remove pizza

 using (var redisClient = new RedisClient()) { var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id); redisClient.Remove(pizzaKey); } 

List of all live pizzas

 using (var redisClient = new RedisClient()) { var livePizzaKeys = redisClient.ScanAllKeys("pizzas:live:*").ToList(); List<Pizza> livePizzas = redisClient.GetValues<Pizza>(livePizzaKeys); } 

Hope this helps.

+17
source share

All Articles