【问题标题】:Updating Service Stack Redis List更新服务栈 Redis 列表
【发布时间】:2014-07-13 08:12:11
【问题描述】:

是否有更新 IRedisList 的正确方法?使用下面的示例代码,我可以修改它以删除列表、更新比萨饼并重新添加列表,但感觉不对。命令行文档非常详尽,但它是一个比我大得多的项目,我不完全确定从哪里开始。

    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 
        }                   
    }

【问题讨论】:

    标签: c# redis servicestack


    【解决方案1】:

    避免列表:

    不幸的是,在这种情况下,Redis 列表并不是一个好的选择。当我开始使用 Redis 时,我遇到了同样的问题,它们似乎是显而易见的选择;)。如果您将 Redis 列表用作只读集,或者您只想弹出和推送,而不是修改列表中间的项目,则 Redis 列表很有用。

    如果您知道项目的索引,您可以“更新” Redis 列表中的项目,但它需要删除重新插入,并且必须是按索引,确定是非常低效的。它通过迭代集合来做到这一点,因为没有本地方法可以做到这一点,这不是一个好主意。 This is a snippetIndexOf 方法的RedisClientList&lt;T&gt;

    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;
    }
    

    所以要完成你的代码,它会是:

    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);
        }                   
    }
    

    但是正如我所说的那样,这不是处理它的好方法。它将检索其他比萨对象的列表,然后遍历它们,直到它与索引匹配。和两个操作更新! :( 在这种情况下最好避免使用列表。

    解决方案:

    当您尝试通过它的 ID 访问比萨饼时,您可以为每个对象创建一个唯一的比萨饼键,这将允许您直接访问比萨饼。所以我们可能会使用:

    pizzas:live:{Id}
    

    示例:

    制作披萨

    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);
    }
    

    按 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);
    }
    

    按 ID 更新比萨饼(只需 GET 和 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
    }
    

    移动到另一个“列表”(也许:当披萨改变状态时)

    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);
    }
    

    删除披萨

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

    列出所有现场披萨

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

    我希望这会有所帮助。

    【讨论】:

    • 鉴于这个答案的年龄。现在有一种有效的方法来更新列表中的条目吗?
    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 2014-09-16
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多