Dynacache doesn't cache data

和自甴很熟 提交于 2019-12-12 05:15:42

问题


I am using Dynacache to cache data that will be eventually returned from a service call - to get things working I am just stubbing the data returned. I am using SimpleInjector for DI and got Dynacache registered with it as pointed out in the answer I got to a previous question

So I have an integration project within my solution which contains the method I want to cache - which currently looks as below:

[CacheableMethod(30)]
public virtual List<MyResponse> GetDataByAccountNumber(int accountNumber)
{
    var response = StubResposne();

    return response;
}

With implementation above Dynacache should cache the data for 30 secs and then clear it. However if I set a breakpoint on the first line in my private StubResponse() method the first time I hit the webpage which uses that data the breakpoint gets hit as expected and the data is returned. However if I refresh the page straight away again I was expecting that as the data would have been cached (as its within 30 secs) then the breakpoint would not have been hit but it is hit everytime?

Is there something incorrect with how I am using Dynacache?


回答1:


This may be due to the way you are registering the class that contains the GetDataByAccountNumber method.

This first test works - if I call the method twice from the same instance I get the cached result back second time around

[Test]
public void GetDataByAccountNumber_CalledTwiceSameInstance_ReturnsCacheSecondTime()
{
    var container = new Container();

    container.Register<IDynaCacheService>(() => new MemoryCacheService());
    container.Register(typeof(TestClass), Cacheable.CreateType<TestClass>());

    var instance = container.GetInstance<TestClass>();

    instance.GetDataByAccountNumber(1);
    instance.GetDataByAccountNumber(2);

    Assert.That(instance.CallerId == 1);
}

If I get 2 different instances from the container then no caching is done

public void GetDataByAccountNumber_CalledTwiceDifferentInstance_DoesNotReturnFromCache()
{
    var container = new Container();

    container.Register<IDynaCacheService>(() => new MemoryCacheService());
    container.Register(typeof(TestClass), Cacheable.CreateType<TestClass>());

    var instance1 = container.GetInstance<TestClass>();

    instance1.GetDataByAccountNumber(1);

    var instance2 = container.GetInstance<TestClass>();

    instance2.GetDataByAccountNumber(2);

    Assert.That(instance2.CallerId == 2);
}

The test class looks like this

public class TestClass
{
    public int CallerId = 0;

    [CacheableMethod(30)] // TODO - put to 20 minutes and have value in WebConfig as constant
    public virtual List<MyResponse> GetDataByAccountNumber(int callerId)
    {
        CallerId = callerId;

        var response = StubResponse();

        return response;
    }

    // ...

Simply registering with a lifetime scope does not appear to be compatible with dynacache. In this test method the container returns the same instance for each call within the scope of the lifetime but the results of the method are not cached ....

[Test]
public void GetDataByAccountNumber_CalledTwiceLifetimeScopedInstance_ReturnsCacheSecondTime()
{
    var container = new Container();

    container.Register<IDynaCacheService>(() => new MemoryCacheService());
    container.Register(typeof(TestClass), Cacheable.CreateType<TestClass>(), new LifetimeScopeLifestyle());

    using (container.BeginLifetimeScope())
    {
        var instance1 = container.GetInstance<TestClass>();

        instance1.GetDataByAccountNumber(1);

        var instance2 = container.GetInstance<TestClass>();

        instance2.GetDataByAccountNumber(2);

        // the container does return the same instance
        Assert.That(instance1, Is.EqualTo(instance2));
        // but the caching does not work
        Assert.That(instance2.CallerId, Is.EqualTo(1));
    }
}

My advice is that you implement caching with decorators which is real easy with Simple Injector - read the articles of @Steven's starting here




回答2:


For registering with SimpleInjector it should be done as below:

container.RegisterSingle<IDynaCacheService>(new MemoryCacheService());
container.Register(typeof(ITestClass), Cacheable.CreateType<TestClass>());

Once I done this Caching worked as expected.

Updated with Full test sample Program

using System;

namespace DynaCacheSimpleInjector

{
    using System.Threading;


using DynaCache;

using SimpleInjector;

class Program
{
    static void Main()
    {
        var container = new Container();

        container.RegisterSingle<IDynaCacheService>(new MemoryCacheService());
        container.Register(typeof(ITestClass), Cacheable.CreateType<TestClass>());

        var instance = container.GetInstance<ITestClass>();

        for (var i = 0; i < 10; i++)
        {
            // Every 2 seconds the output will change
            Console.WriteLine(instance.GetData(53));
            Thread.Sleep(500);
        }
    }
}

public class TestClass : ITestClass
{
    [CacheableMethod(2)]
    public virtual string GetData(int id)
    {
        return String.Format("{0} - produced at {1}", id, DateTime.Now);
    }
}

public interface ITestClass
{
    string GetData(int id);
}

}



来源:https://stackoverflow.com/questions/24283202/dynacache-doesnt-cache-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!