Evite listas:
Infelizmente, as listas do Redis não são realmente uma boa escolha nesta situação. Eu tive o mesmo problema quando comecei a usar o Redis, eles parecem a escolha óbvia;). As listas do Redis são úteis se você as estiver usando como um conjunto somente leitura ou se quiser apenas pop e push, mas não para modificar um item no meio da lista.
Você pode "atualizar" itens em uma lista Redis se souber o índice do item, mas é necessário remover e re-insira , e deve ser por índice, cuja determinação é terrivelmente ineficiente. Ele faz isso iterando a coleção, porque não há uma maneira nativa de fazer isso, e isso não é uma boa ideia. Este é um trecho do
IndexOf
método do 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;
}
Então, para completar seu código, seria:
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);
}
}
Mas esta não é uma boa maneira de lidar com isso como eu disse. Ele recuperará a lista dos outros objetos pizza e, em seguida, iterará sobre eles até que corresponda ao índice. E duas operações para atualizar! :( Melhor evitar listas nesta situação.
Solução:
Como você está tentando acessar a pizza por seu ID, você pode criar uma chave de pizza exclusiva para cada objeto, isso permitirá que você acesse a pizza diretamente. Então podemos usar:
pizzas:live:{Id}
Exemplos:
Criar uma 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);
}
Ganhe uma pizza por 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);
}
Atualizar uma pizza por ID (Simplesmente um GET e 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
}
Mover para outra "lista" (talvez:quando uma pizza muda de estado)
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);
}
Excluir uma pizza
using (var redisClient = new RedisClient())
{
var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
redisClient.Remove(pizzaKey);
}
Liste todas as pizzas ao vivo
using (var redisClient = new RedisClient())
{
var livePizzaKeys = redisClient.ScanAllKeys("pizzas:live:*").ToList();
List<Pizza> livePizzas = redisClient.GetValues<Pizza>(livePizzaKeys);
}
Eu espero que isso ajude.