1

我正在尝试使用 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");

然后我取回我的对象​​,但即使在超时之后也应该删除它。

4

1 回答 1

2

好吧,我想我明白了。这似乎是 TypedRedisClient 和/或处理键的方式的错误。

我将在此处发布我的解决方案,以供其他在这个简单场景中遇到问题的人使用 Redis 作为持久缓存并且并不真正关心 Sets、Hashes 等的额外功能......

添加以下扩展方法:

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

    }
}

然后我把我的测试代码改成这个。显然这是草率的,需要改进,但至少我的测试按预期工作。

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;
            }
        }
    }
}
于 2013-01-28T12:13:50.223 回答