Éviter les listes :
Malheureusement, les listes Redis ne sont pas vraiment un bon choix dans cette situation. J'ai eu le même problème quand j'ai commencé à utiliser Redis, ils semblent être le choix évident ;). Les listes Redis sont utiles si vous les utilisez comme un ensemble en lecture seule, ou si vous voulez simplement faire apparaître et pousser, mais pas pour modifier un élément au milieu de la liste.
Vous pouvez "mettre à jour" des éléments dans une liste Redis si vous connaissez l'index de l'élément, mais cela nécessite de supprimer et réinsérer , et ce doit être par index, dont la détermination est horriblement inefficace. Il le fait en itérant la collection, car il n'existe aucun moyen natif de le faire, et ce n'est pas une bonne idée. Ceci est un extrait de l'IndexOf
méthode de la RedisClientList<T>
.
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;
}
Donc pour compléter votre code, ce serait :
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);
}
}
Mais ce n'est pas une bonne façon de le gérer comme je l'ai dit. Il récupérera la liste des autres objets pizza puis les parcourra jusqu'à ce qu'il corresponde à l'index. Et deux opérations à mettre à jour ! :( Mieux vaut éviter les listes dans cette situation.
Solution :
Lorsque vous essayez d'accéder à la pizza par son identifiant, vous pouvez créer une clé de pizza unique pour chaque objet, cela vous permettra d'accéder directement à la pizza. Nous pourrions donc utiliser :
pizzas:live:{Id}
Exemples :
Créer une 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);
}
Obtenir une pizza par 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);
}
Mettre à jour une pizza par identifiant (Simplement un GET et 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
}
Déplacer vers une autre "liste" (peut-être :lorsqu'une pizza change d'état)
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);
}
Supprimer une pizza
using (var redisClient = new RedisClient())
{
var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
redisClient.Remove(pizzaKey);
}
Répertorier toutes les pizzas en direct
using (var redisClient = new RedisClient())
{
var livePizzaKeys = redisClient.ScanAllKeys("pizzas:live:*").ToList();
List<Pizza> livePizzas = redisClient.GetValues<Pizza>(livePizzaKeys);
}
J'espère que cela vous aidera.