Listas a evitar:
Desafortunadamente, las listas de Redis no son realmente una buena opción. en esta situación. Tuve el mismo problema cuando comencé a usar Redis, parecen ser la opción obvia;). Las listas de Redis son útiles si las usa como un conjunto de solo lectura, o si solo desea hacer estallar y empujar, pero no para modificar un elemento en el medio de la lista.
Puede "actualizar" elementos en una lista de Redis si conoce el índice del elemento, pero requiere eliminar y volver a insertar , y debe ser por índice, cuya determinación es terriblemente ineficiente. Lo hace iterando la colección, porque no hay una forma nativa de hacerlo, y no es una buena idea. Este es un fragmento del IndexOf
método de 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;
}
Entonces, para completar su código, sería:
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);
}
}
Pero esta no es una buena manera de manejarlo como he dicho. Recuperará la lista de los otros objetos de pizza y luego iterará sobre ellos hasta que coincida con el índice. ¡Y dos operaciones para actualizar! :( Es mejor evitar las listas en esta situación.
Solución:
Mientras intenta acceder a la pizza por su ID, puede crear una clave de pizza única para cada objeto, esto le permitirá acceder a la pizza directamente. Así que podríamos usar:
pizzas:live:{Id}
Ejemplos:
Crear una 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);
}
Obtener una pizza por identificación
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);
}
Actualizar una pizza por ID (Simplemente un GET y 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 a otra "lista" (tal vez:cuando una pizza cambia 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);
}
Eliminar una pizza
using (var redisClient = new RedisClient())
{
var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
redisClient.Remove(pizzaKey);
}
Lista de todas las pizzas en vivo
using (var redisClient = new RedisClient())
{
var livePizzaKeys = redisClient.ScanAllKeys("pizzas:live:*").ToList();
List<Pizza> livePizzas = redisClient.GetValues<Pizza>(livePizzaKeys);
}
Espero que esto ayude.