我已经阅读了大量关于MVC应用程序中的页面缓存和部分页面缓存的信息。然而,我想知道你将如何缓存数据。
在我的场景中,我将使用LINQ到实体(实体框架)。在第一次调用GetNames(或任何方法)时,我想从数据库中获取数据。我想将结果保存在缓存中,并在第二次调用时使用缓存版本(如果存在)。
谁能举例说明这将如何工作,这应该在哪里实现(模型?),如果它将工作。
我在传统的ASP中见过这种情况。NET应用程序,通常用于非常静态的数据。
我已经阅读了大量关于MVC应用程序中的页面缓存和部分页面缓存的信息。然而,我想知道你将如何缓存数据。
在我的场景中,我将使用LINQ到实体(实体框架)。在第一次调用GetNames(或任何方法)时,我想从数据库中获取数据。我想将结果保存在缓存中,并在第二次调用时使用缓存版本(如果存在)。
谁能举例说明这将如何工作,这应该在哪里实现(模型?),如果它将工作。
我在传统的ASP中见过这种情况。NET应用程序,通常用于非常静态的数据。
当前回答
扩展@Hrvoje Hudo的回答…
代码:
using System;
using System.Runtime.Caching;
public class InMemoryCache : ICacheService
{
public TValue Get<TValue>(string cacheKey, int durationInMinutes, Func<TValue> getItemCallback) where TValue : class
{
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, int durationInMinutes, Func<TId, TValue> getItemCallback) where TValue : class
{
string cacheKey = string.Format(cacheKeyFormat, id);
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback(id);
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
}
interface ICacheService
{
TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback) where TValue : class;
TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback) where TValue : class;
}
例子
单项缓存(当每个项都基于其ID进行缓存时,因为为该项类型缓存整个目录将过于密集)。
Product product = cache.Get("product_{0}", productId, 10, productData.getProductById);
缓存所有东西
IEnumerable<Categories> categories = cache.Get("categories", 20, categoryData.getCategories);
何必TId
第二个帮助器特别好,因为大多数数据键都不是复合的。如果经常使用复合键,可以添加其他方法。通过这种方式,您可以避免进行各种字符串连接或字符串。格式以获取要传递给缓存助手的键。它还使传递数据访问方法更容易,因为您不必将ID传递到包装器方法中……对于大多数用例来说,整个过程变得非常简洁和一致。
其他回答
扩展@Hrvoje Hudo的回答…
代码:
using System;
using System.Runtime.Caching;
public class InMemoryCache : ICacheService
{
public TValue Get<TValue>(string cacheKey, int durationInMinutes, Func<TValue> getItemCallback) where TValue : class
{
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, int durationInMinutes, Func<TId, TValue> getItemCallback) where TValue : class
{
string cacheKey = string.Format(cacheKeyFormat, id);
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback(id);
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
}
interface ICacheService
{
TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback) where TValue : class;
TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback) where TValue : class;
}
例子
单项缓存(当每个项都基于其ID进行缓存时,因为为该项类型缓存整个目录将过于密集)。
Product product = cache.Get("product_{0}", productId, 10, productData.getProductById);
缓存所有东西
IEnumerable<Categories> categories = cache.Get("categories", 20, categoryData.getCategories);
何必TId
第二个帮助器特别好,因为大多数数据键都不是复合的。如果经常使用复合键,可以添加其他方法。通过这种方式,您可以避免进行各种字符串连接或字符串。格式以获取要传递给缓存助手的键。它还使传递数据访问方法更容易,因为您不必将ID传递到包装器方法中……对于大多数用例来说,整个过程变得非常简洁和一致。
适用于。net 4.5+框架
添加reference: System.Runtime.Caching
添加using语句: 使用System.Runtime.Caching;
public string[] GetNames()
{
var noms = System.Runtime.Caching.MemoryCache.Default["names"];
if(noms == null)
{
noms = DB.GetNames();
System.Runtime.Caching.MemoryCache.Default["names"] = noms;
}
return ((string[])noms);
}
在. net Framework 3.5和更早的版本中,ASP。NET在System.Web.Caching命名空间中提供了内存中的缓存实现。在以前版本的. net Framework中,缓存仅在系统中可用。Web命名空间,因此需要依赖于ASP。网类。在. net Framework 4中,System.Runtime.Caching命名空间包含为Web和非Web应用程序设计的api。
更多信息:
https://msdn.microsoft.com/en-us/library/dd997357 (v = vs.110) . aspx https://learn.microsoft.com/en-us/dotnet/framework/performance/caching-in-net-framework-applications
public sealed class CacheManager
{
private static volatile CacheManager instance;
private static object syncRoot = new Object();
private ObjectCache cache = null;
private CacheItemPolicy defaultCacheItemPolicy = null;
private CacheEntryRemovedCallback callback = null;
private bool allowCache = true;
private CacheManager()
{
cache = MemoryCache.Default;
callback = new CacheEntryRemovedCallback(this.CachedItemRemovedCallback);
defaultCacheItemPolicy = new CacheItemPolicy();
defaultCacheItemPolicy.AbsoluteExpiration = DateTime.Now.AddHours(1.0);
defaultCacheItemPolicy.RemovedCallback = callback;
allowCache = StringUtils.Str2Bool(ConfigurationManager.AppSettings["AllowCache"]); ;
}
public static CacheManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new CacheManager();
}
}
}
return instance;
}
}
public IEnumerable GetCache(String Key)
{
if (Key == null || !allowCache)
{
return null;
}
try
{
String Key_ = Key;
if (cache.Contains(Key_))
{
return (IEnumerable)cache.Get(Key_);
}
else
{
return null;
}
}
catch (Exception)
{
return null;
}
}
public void ClearCache(string key)
{
AddCache(key, null);
}
public bool AddCache(String Key, IEnumerable data, CacheItemPolicy cacheItemPolicy = null)
{
if (!allowCache) return true;
try
{
if (Key == null)
{
return false;
}
if (cacheItemPolicy == null)
{
cacheItemPolicy = defaultCacheItemPolicy;
}
String Key_ = Key;
lock (Key_)
{
return cache.Add(Key_, data, cacheItemPolicy);
}
}
catch (Exception)
{
return false;
}
}
private void CachedItemRemovedCallback(CacheEntryRemovedArguments arguments)
{
String strLog = String.Concat("Reason: ", arguments.RemovedReason.ToString(), " | Key-Name: ", arguments.CacheItem.Key, " | Value-Object: ", arguments.CacheItem.Value.ToString());
LogManager.Instance.Info(strLog);
}
}
我用过这种方法,对我很有效。 https://msdn.microsoft.com/en-us/library/system.web.caching.cache.add (v = vs.110) . aspx system.web. cache. cache.add的参数信息。
public string GetInfo()
{
string name = string.Empty;
if(System.Web.HttpContext.Current.Cache["KeyName"] == null)
{
name = GetNameMethod();
System.Web.HttpContext.Current.Cache.Add("KeyName", name, null, DateTime.Noew.AddMinutes(5), Cache.NoSlidingExpiration, CacheitemPriority.AboveNormal, null);
}
else
{
name = System.Web.HttpContext.Current.Cache["KeyName"] as string;
}
return name;
}
我要说的是,如果您发现以前的解决方案非常复杂,那么在这个持久化数据问题上实现Singleton可以是一个解决方案
public class GPDataDictionary
{
private Dictionary<string, object> configDictionary = new Dictionary<string, object>();
/// <summary>
/// Configuration values dictionary
/// </summary>
public Dictionary<string, object> ConfigDictionary
{
get { return configDictionary; }
}
private static GPDataDictionary instance;
public static GPDataDictionary Instance
{
get
{
if (instance == null)
{
instance = new GPDataDictionary();
}
return instance;
}
}
// private constructor
private GPDataDictionary() { }
} // singleton