c# - WCF:如何在客户端缓存来自 OData 的集合

标签 c# wcf caching client odata

是否有可能缓存使用 WCF 从 OData 服务检索的集合。

情况如下: 我使用 odata 服务的元数据通过 Visual Studio 2015 生成了一个 WCF 服务客户端。 VS生成了一个继承自System.Data.Services.Client.DataServiceContext的类.此类具有 System.Data.Services.Client.DataServiceQuery<T> 类型的一些属性.其中一些属性的数据很少更改。由于性能原因,我希望 WCF 客户端仅在第一次而不是每次我在代码中使用它时加载这些属性。

是否有内置的可能性来缓存这些属性的数据?或者我可以告诉服务客户端不要每次都重新加载特定属性。

假设服务客户端类是ODataClient它的属性之一是“面积”,现在我通过以下方式获取值:

var client = new ODataClient("url_to_the_service");
client.IgnoreMissingProperties = true;

var propertyInfo = client.GetType().GetProperty("Area");
var area = propertyInfo.GetValue(client) as IEnumerable<object>;

我之所以以如此复杂的方式这样做,是因为客户端应该非常通用:可以在配置文件中配置要处理的属性。

* 编辑 *

我已经尝试在 System.Data.Services.Client.DataServiceContext 中查找属性类或 System.Data.Services.Client.DataServiceQuery<T>缓存类。但我找不到任何内容。

最佳答案

据我所知,客户端没有“开箱即用”的缓存概念。有一些选项可以在服务器上缓存请求的输出,这也是您可能需要考虑的。谷歌搜索“WCF 缓存”将为您提供大量相关信息。

关于客户端缓存...@Evk 是正确的,它非常简单。这是使用 MemoryCache 的示例.

using System;
using System.Runtime.Caching;

namespace Services.Util
{
    public class CacheWrapper : ICacheWrapper
    {
        ObjectCache _cache = MemoryCache.Default;

        public void ClearCache()
        {
            MemoryCache.Default.Dispose();
            _cache = MemoryCache.Default;
        }

        public T GetFromCache<T>(string key, Func<T> missedCacheCall)
        {
            return GetFromCache<T>(key, missedCacheCall, TimeSpan.FromMinutes(5));
        }

        public T GetFromCache<T>(string key, Func<T> missedCacheCall, TimeSpan timeToLive)
        {
            var result = _cache.Get(key);
            if (result == null)
            {
                result = missedCacheCall();
                if (result != null)
                {
                    _cache.Set(key, result, new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.Add(timeToLive) });
                }
            }

            return (T)result;
        }

        public void InvalidateCache(string key)
        {
            _cache.Remove(key);
        }
    }
}

这是一个使用缓存的代码示例...

private class DataAccessTestStub
        {
            public const string DateTimeTicksCacheKey = "GetDateTimeTicks";

            ICacheWrapper _cache;

            public DataAccessTestStub(ICacheWrapper cache)
            {
                _cache = cache;
            }

            public string GetDateTimeTicks()
            {
                return _cache.GetFromCache(DateTimeTicksCacheKey, () =>
                {
                    var result = DateTime.Now.Ticks.ToString();
                    Thread.Sleep(100); // Create some delay
                    return result;
                });
            }

            public string GetDateTimeTicks(TimeSpan timeToLive)
            {
                return _cache.GetFromCache(DateTimeTicksCacheKey, () =>
                {
                    var result = DateTime.Now.Ticks.ToString();
                    Thread.Sleep(500); // Create some delay
                    return result;
                }, timeToLive);
            }

            public void ClearDateTimeTicks()
            {
                _cache.InvalidateCache(DateTimeTicksCacheKey);
            }

            public void ClearCache()
            {
                _cache.ClearCache();
            }
        }

如果你喜欢,还有一些测试......

 [TestClass]
public class CacheWrapperTest
{
    private DataAccessTestStub _dataAccessTestClass;

    [TestInitialize]
    public void Init()
    {
        _dataAccessTestClass = new DataAccessTestStub(new CacheWrapper());
    }

    [TestMethod]
    public void GetFromCache_ShouldExecuteCacheMissCall()
    {
        var original = _dataAccessTestClass.GetDateTimeTicks();
        Assert.IsNotNull(original);
    }

    [TestMethod]
    public void GetFromCache_ShouldReturnCachedVersion()
    {
        var copy1 = _dataAccessTestClass.GetDateTimeTicks();
        var copy2 = _dataAccessTestClass.GetDateTimeTicks();
        Assert.AreEqual(copy1, copy2);
    }

    [TestMethod]
    public void GetFromCache_ShouldRespectTimeToLive()
    {
        _dataAccessTestClass.ClearDateTimeTicks();
        var copy1 = _dataAccessTestClass.GetDateTimeTicks(TimeSpan.FromSeconds(2));
        var copy2 = _dataAccessTestClass.GetDateTimeTicks();
        Assert.AreEqual(copy1, copy2);

        Thread.Sleep(3000);
        var copy3 = _dataAccessTestClass.GetDateTimeTicks();
        Assert.AreNotEqual(copy1, copy3);
    }

    [TestMethod]
    public void InvalidateCache_ShouldClearCachedVersion()
    {
        var original = _dataAccessTestClass.GetDateTimeTicks();

        _dataAccessTestClass.ClearDateTimeTicks();

        var updatedVersion = _dataAccessTestClass.GetDateTimeTicks();
        Assert.AreNotEqual(original, updatedVersion);
    }

}

关于c# - WCF:如何在客户端缓存来自 OData 的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36063714/

相关文章:

java - Apache Ignite 以编程方式销毁持久缓存

c# - 在等待 WaitHandle 时运行消息循环

c# - 通过将方法作为变量发送来简化代码

c# - 使用动态对象时出现 RuntimeBinderException

ios - 从 iOS5 中发现 WCF Rest 服务

wcf - 访问仅启用 TLS 1.2 的服务器上运行的 WCF 服务

caching - 某些 Google CDN 资源的有效期很短

c# - Nest和ElasticSearch-UpdateSettings

java - 使用 WSHttpBinding 的 WCF 和 Java Interop,

pandas - 如何实现在 REST API 调用之间缓存 Pandas 数据帧值?