在我的场景中,我有一个连接到WebApi2的Winforms客户端。数据存储在SQL Server数据库中。
为了提高性能,我正在研究将数据存储在本地缓存中是否可行。优选地,本地高速缓存应该存储在文件中而不是保存在存储器中,因为RAM可能是个问题。数据是所有POCO类,有些比其他类复杂得多,并且大多数类彼此相关。
我列出了哪些框架可行的候选名单:
使用MemoryCache
,我需要实现自己的解决方案,但它符合我的初始要求。
然而,我看到的一个常见问题是更新相关类。例如,我在CustomerAddress
和PostCode
之间存在关系。如果我更改邮政编码对象中的某些属性,我可以轻松更新其本地缓存。但是如何更新/无效使用此邮政编码的任何其他类,在这种情况下CustomerAddress
?
上面的任何框架是否都有帮助这种情况的方法,还是完全依赖于开发人员来处理这种缓存失效?
答案 0 :(得分:1)
为了加快性能,我正在研究是否在本地存储数据 缓存是一个可行的解决方案优选地,本地缓存应该是 存储在文件中而不是保存在内存中,因为RAM可能是一个问题
整个问题是避免将其存储在文件中,以避免缓慢的DISK操作,因此Redis是基于RAM的内存。
上面的任何框架都有这种方法有帮助吗? 情况,还是完全依赖于开发人员来处理 这样的缓存失效?
您可以将整个对象保存为JSON,而不是应用逻辑并反汇编对象,这在应用更改时也会很慢并且容易出错。
答案 1 :(得分:1)
CachingFramework.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; }
}
我的建议是:
这样的事情应该可行:
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) });
}
}