ServiceStack.Redis存储具有超时的对象并按键检索

时间:2013-01-27 20:02:44

标签: c# redis servicestack

我正在尝试使用ServiceStack.Redis客户端从memcached转移到redis。我希望能够简单地检查Redis缓存是否按键分配项目,如果没有添加过期超时。然后如果它们存在则检索它们。

为了测试这个,我创建了一个简单的ASP.NET WebApi项目,并使用这两种方法修改了ValuesController。

public class ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        using (var redisClient = new RedisClient("localhost"))
        {
            IRedisTypedClient<IEnumerable<SampleEvent>> redis = redisClient.As<IEnumerable<SampleEvent>>();

            if (!redis.ContainsKey("urn:medications:25"))
            {
                var medsWithID25 = new List<SampleEvent>();
                medsWithID25.Add(new SampleEvent() { ID = 1, EntityID = "25", Name = "Digoxin" });
                medsWithID25.Add(new SampleEvent() { ID = 2, EntityID = "25", Name = "Aspirin" });

                redis.SetEntry("urn:medications:25", medsWithID25);
                redis.ExpireIn("urn:medications:25", TimeSpan.FromSeconds(30));
            }

        }

        return new string[] { "1", "2" };
    }

    public SampleEvent Get(int id)
    {
        using (var redisClient = new RedisClient("localhost"))
        {
            IRedisTypedClient<IEnumerable<SampleEvent>> redis = redisClient.As<IEnumerable<SampleEvent>>();
            IEnumerable<SampleEvent> events = redis.GetById("urn:medications:25");

            if (events != null)
            {
                return events.Where(m => m.ID == id).SingleOrDefault();
            }
            else
                return null;
        }
    }
}

这似乎不起作用。 redis.GetById始终返回null。我做错了什么?

感谢。

更新1:

如果我将获取数据的行更改为:

IEnumerable<SampleEvent> events = redis.GetValue("urn:medications:25");

然后我恢复了我的对象,但即使在超时后也应该删除它。

1 个答案:

答案 0 :(得分:2)

好的,我想我明白了。它似乎与TypedRedisClient和/或处理密钥的方式有关。

我会在这里发布我的解决方案给其他人在这个简单的场景中遇到问题,我想将Redis用作持久缓存而不关心集合,哈希等的额外功能......

添加以下扩展方法:

using System;
using System.Text;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using ServiceStack.OrmLite;
using ServiceStack.Common;
using ServiceStack.Common.Utils;
using ServiceStack.DesignPatterns.Model;
using ServiceStack.ServiceInterface;
using ServiceStack.CacheAccess;
using ServiceStack.ServiceHost;
using ServiceStack.Redis;

namespace Redis.Extensions
{
    public static class RedisExtensions
    {
        internal static T GetFromCache<T>(this IRedisClient redisClient, string cacheKey,
            Func<T> factoryFn,
            TimeSpan expiresIn)
        {
            var res = redisClient.Get<T>(cacheKey);
            if (res != null)
            {
                redisClient.Set<T>(cacheKey, res, expiresIn);
                return res;
            }
            else
            {
                res = factoryFn();
                if (res != null) redisClient.Set<T>(cacheKey, res, expiresIn);
                return res;
            }
        }

    }
}

然后我将测试代码更改为此。显然这很邋and,需要改进,但至少我的测试按预期工作。

using ServiceStack.Redis;
using ServiceStack.Redis.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Redis.Extensions;

namespace RedisTestsWithBooksleeve.Controllers
{
    public class SampleEvent
    {
        public int ID { get; set; }
        public string EntityID { get; set; }
        public string Name { get; set; }
    }

    public class ValuesController : ApiController
    {
        public IEnumerable<string> Get()
        {
            using (var redisClient = new RedisClient("localhost"))
            {
                if (!redisClient.ContainsKey("Meds25"))
                {

                    redisClient.GetFromCache<IEnumerable<SampleEvent>>("Meds25", () => { 

                        var medsWithID25 = new List<SampleEvent>();
                        medsWithID25.Add(new SampleEvent() { ID = 1, EntityID = "25", Name = "Digoxin" });
                        medsWithID25.Add(new SampleEvent() { ID = 2, EntityID = "25", Name = "Aspirin" });

                        return medsWithID25;

                    }, TimeSpan.FromSeconds(5));
                }

            }

            return new string[] { "1", "2" };
        }

        public SampleEvent Get(int id)
        {
            using (var redisClient = new RedisClient("localhost"))
            {
                IEnumerable<SampleEvent> events = redisClient.GetFromCache<IEnumerable<SampleEvent>>("Meds25", () =>
                {

                    var medsWithID25 = new List<SampleEvent>();
                    medsWithID25.Add(new SampleEvent() { ID = 1, EntityID = "25", Name = "Digoxin" });
                    medsWithID25.Add(new SampleEvent() { ID = 2, EntityID = "25", Name = "Aspirin" });

                    return medsWithID25;

                }, TimeSpan.FromSeconds(5));

                if (events != null)
                {
                    return events.Where(m => m.ID == id).SingleOrDefault();
                }
                else
                    return null;
            }
        }
    }
}