Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Redis是本地缓存的可行解决方案吗?_C#_Winforms_Caching_Asp.net Web Api_Redis - Fatal编程技术网

C# Redis是本地缓存的可行解决方案吗?

C# Redis是本地缓存的可行解决方案吗?,c#,winforms,caching,asp.net-web-api,redis,C#,Winforms,Caching,Asp.net Web Api,Redis,在我的场景中,我有一个连接到WebApi2的Winforms客户端。数据存储在SQL Server数据库中 为了提高性能,我正在研究在本地缓存中存储数据是否是可行的解决方案。最好,本地缓存应该存储在文件中,而不是保存在内存中,因为RAM可能是一个问题。数据都是POCO类,有些类比其他类复杂得多,大多数类都是相互关联的 我列出了哪些框架可能可行的短名单: 记忆卡 MemCached 缓存管理器 StackExchange.Redis 本地数据库 使用MemoryCache,我需要实现自己的解决方案

在我的场景中,我有一个连接到WebApi2的Winforms客户端。数据存储在SQL Server数据库中

为了提高性能,我正在研究在本地缓存中存储数据是否是可行的解决方案。最好,本地缓存应该存储在文件中,而不是保存在内存中,因为RAM可能是一个问题。数据都是POCO类,有些类比其他类复杂得多,大多数类都是相互关联的

我列出了哪些框架可能可行的短名单:

  • 记忆卡
  • MemCached
  • 缓存管理器
  • StackExchange.Redis
  • 本地数据库
  • 使用
    MemoryCache
    ,我需要实现自己的解决方案,但它将满足我最初的需求

    然而,我看到的一个常见问题是相关类的更新。例如,我在
    CustomerAddress
    PostCode
    之间有一种关系。如果我更改postcode对象中的某些属性,我可以轻松地更新其本地缓存。但是,在本例中,
    CustomerAddress
    ,如何更新/使使用此邮政编码的任何其他类无效

    上面的任何一个框架都有在这种情况下有帮助的方法吗,还是完全依赖于开发人员来处理这种缓存失效

    为了提高性能,我正在研究是否在本地存储数据 缓存是一个可行的解决方案。优选地,本地缓存应该是 存储在文件中而不是作为RAM保存在内存中可能是一个问题

    整个问题是避免将其存储在文件中,避免磁盘操作太慢,因此Redis是基于RAM的内存

    上面的任何一个框架都有这种帮助的方法吗 情况的不同,还是完全取决于开发人员来处理 这样的缓存失效

    您可以将整个对象保存为JSON,而不是应用逻辑并反汇编对象,这在应用更改时也会很慢且容易出错。

    该库提供了一种将标记与键和哈希关联的机制,这样您就可以在一次操作中使它们失效

    我假设你会:

    • 使用“Address:{AddressId}”这样的键将客户地址存储在Redis中
    • 使用“PostCode:{PostCodeId}”键将邮政编码存储在Redis中
    你的模型是这样的:

    public class CustomerAddress
    {
        public int CustomerAddressId { get; set; }
        public int CustomerId { get; set; }
        public int PostCodeId { get; set; }
    }
    public class PostCode
    {
        public int PostCodeId { get; set; }
        public string Code { get; set; }
    }
    
    我的建议是:

    • 在Redis上用类似“Tag PostCode:{PostCodeId}”的标记标记客户地址对象
    • 使用从缓存/数据库检索客户地址和邮政编码
    • 更改邮政编码时,按标记使缓存对象无效
    类似这样的方法可能会奏效:

    public class DataAccess
    {
        private Context _cacheContext = new CachingFramework.Redis.Context("localhost:6379");
    
        private string FormatPostCodeKey(int postCodeId)
        {
            return string.Format("PostCode:{0}", postCodeId);
        }
    
        private string FormatPostCodeTag(int postCodeId)
        {
            return string.Format("Tag-PostCode:{0}", postCodeId);
        }
    
        private string FormatAddressKey(int customerAddressId)
        {
            return string.Format("Address:{0}", customerAddressId);
        }
    
        public void InsertPostCode(PostCode postCode)
        {
            Sql.InsertPostCode(postCode);
        }
    
        public void UpdatePostCode(PostCode postCode)
        {
            Sql.UpdatePostCode(postCode);
            //Invalidate cache: remove CustomerAddresses and PostCode related
            _cacheContext.Cache.InvalidateKeysByTag(FormatPostCodeTag(postCode.PostCodeId));
        }
    
        public void DeletePostCode(int postCodeId)
        {
            Sql.DeletePostCode(postCodeId);
            _cacheContext.Cache.InvalidateKeysByTag(FormatPostCodeTag(postCodeId));
        }
    
        public PostCode GetPostCode(int postCodeId)
        {
            // Get/Insert the postcode from/into Cache with key = PostCode{PostCodeId}. 
            // Mark the object with tag = Tag-PostCode:{PostCodeId}
            return _cacheContext.Cache.FetchObject(
                FormatPostCodeKey(postCodeId),              // Redis Key to use
                () => Sql.GetPostCode(postCodeId),          // Delegate to get the value from database
                new[] { FormatPostCodeTag(postCodeId) });   // Tags related
        }
    
        public void InsertCustomerAddress(CustomerAddress customerAddress)
        {
            Sql.InsertCustomerAddress(customerAddress);
        }
    
        public void UpdateCustomerAddress(CustomerAddress customerAddress)
        {
            var updated = Sql.UpdateCustomerAddress(customerAddress);
            if (updated.PostCodeId != customerAddress.PostCodeId)
            {
                var addressKey = FormatAddressKey(customerAddress.CustomerAddressId);
                _cacheContext.Cache.RenameTagForKey(addressKey, FormatPostCodeTag(customerAddress.PostCodeId), FormatPostCodeTag(updated.PostCodeId));
            }
        }
    
        public void DeleteCustomerAddress(CustomerAddress customerAddress)
        {
            Sql.DeleteCustomerAddress(customerAddress.CustomerAddressId);
            //Clean-up, remove the postcode tag from the CustomerAddress:
            _cacheContext.Cache.RemoveTagsFromKey(FormatAddressKey(customerAddress.CustomerAddressId), new [] { FormatPostCodeTag(customerAddress.PostCodeId) });
        }
    
        public CustomerAddress GetCustomerAddress(int customerAddressId)
        {
            // Get/Insert the address from/into Cache with key = Address:{CustomerAddressId}. 
            // Mark the object with tag = Tag-PostCode:{PostCodeId}
            return _cacheContext.Cache.FetchObject(
                FormatAddressKey(customerAddressId),
                () => Sql.GetCustomerAddress(customerAddressId),
                a => new[] { FormatPostCodeTag(a.PostCodeId) });
        }
    }
    

    如果相关对象发生更改,会发生什么情况?与之相关的对象是否也会被更新?不,它只是一个内存容器,没有双向绑定,这是您处理更新Redis的内容和时间的部分。计算机科学中只有两个难题:缓存失效和命名PhilKarlton库(SE.Redis的包装器)可以使用简单的标记机制使键和散列无效。还有@thepirat000是一个使用这些功能的例子,我可以遵循吗?