1

ServiceStack.Redis クライアントを使用して memcached から redis に移行しようとしています。Redis キャッシュにキーでアイテムがあるかどうかを確認し、そうでない場合は有効期限のタイムアウトでそれらを追加できるようにしたいと思います。それらが存在する場合は、後でそれらを取得します。

これをテストするために、単純な ASP.NET WebApi プロジェクトを作成し、これら 2 つのメソッドで 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 を永続的なキャッシュとして使用したいが、セットやハッシュなどの追加機能はあまり気にしないこの単純なシナリオで問題を抱えている他の人のために、ここに私のソリューションを投稿します...

次の拡張メソッドを追加します。

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 に答える