如何缓存数据库表以防止在 Asp.net C# mvc 中出现许多数据库查询
Posted
技术标签:
【中文标题】如何缓存数据库表以防止在 Asp.net C# mvc 中出现许多数据库查询【英文标题】:How to cache database tables to prevent many database queries in Asp.net C# mvc 【发布时间】:2013-07-13 06:02:20 【问题描述】:我使用 Asp.net mvc 4 (c#) 构建自己的 cms,我想缓存一些数据库数据,例如:本地化、搜索类别(它是长尾的,每个类别都有自己的子和子子类别) 等。
一直查询数据库有点过头了,因为每个页面请求可能会超过 30-100 次查询,但是用户很少更新这些数据库
那么最好的方法(性能和便利性)是什么?
我知道如何使用动作的OutputCache,但这不是我在这种情况下需要的,它是缓存html,但我需要的是例如我自己的助手@html.Localization("Newsletter.Tite")
将获取语言的值,或与数据等交互的任何其他助手。
我认为(不太确定)我需要缓存我想要的数据,只有在第一次调用应用程序时,然后使用缓存位置,但我什至没有任何经验它。
【问题讨论】:
你目前在做什么,为什么不工作? Romoku,我对数据库进行简单的 c# linq 查询,这有点矫枉过正,因为每个页面请求都有很多请求 【参考方案1】:您可以使用内置的MemoryCache
来存储您从数据库中检索到的整个结果集。
一个典型的模式:
MyModel model = MemoryCache.Default["my_model_key"] as MyModel;
if (model == null)
model = GetModelFromDatabase();
MemoryCache.Default["my_model_key"] = model;
// you could use the model here
【讨论】:
这是最好的方法吗?我可以找到很多方法,但我不知道什么是最好的 最佳是一个主观概念。 MemoryCache 具有很强的可扩展性,是 .NET 4.0 中引入的新缓存机制。它可以很容易地扩展到使用分布式缓存,例如 memcached,如果您在 webfarm 中运行您的网站,这是必须的。 然后继续使用 MemoryCache。 MemoryCache 对数据库表一无所知。它适用于 .NET 对象。因此,理论上,如果您将数据库表加载到某个 .NET 对象(或对象集合)中,则可以将其存储到 MemoryCache 中,如我的回答所示。 其实你不应该扩展 MemoryCache。您应该扩展 ObjectCache。 Memcached 已经提供了可以直接使用的实现。你说的对。我没有正确表达自己。【参考方案2】:我必须缓存常见的数据库数据,例如下拉菜单中显示的数据。我用MemoryCache
。我使用Entity Framework code first
和Autofac
进行依赖注入。
这是我在解决方案中所做的一部分,可能不适合你,但它适合我,虽然并不完美,但需要大量清理工作。
我的ICacheManager
界面:
public interface ICacheManager
T Get<T>(string key);
void Set(string key, object data, int cacheTime);
bool IsSet(string key);
void Remove(string key);
void Clear();
我的CacheManager
班级:
public class CacheManager : ICacheManager
private ObjectCache Cache
get
return MemoryCache.Default;
public T Get<T>(string key)
return (T)Cache[key];
public void Set(string key, object data, int cacheTime)
if (data == null)
return;
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
public bool IsSet(string key)
return (Cache.Contains(key));
public void Remove(string key)
Cache.Remove(key);
public void Clear()
foreach (var item in Cache)
Remove(item.Key);
我的缓存扩展类:
public static class CacheExtensions
public static T Get<T>(this ICacheManager cacheManager, string key, Func<T> acquire)
return Get(cacheManager, key, 60, acquire);
public static T Get<T>(this ICacheManager cacheManager, string key, int cacheTime, Func<T> acquire)
if (cacheManager.IsSet(key))
return cacheManager.Get<T>(key);
else
var result = acquire();
cacheManager.Set(key, result, cacheTime);
return result;
这就是我在存储库类中使用它的方式。此方法返回我所有银行的列表,该列表显示在下拉列表中。
public class BankRepository : RepositoryBase<Bank>, IBankRepository
private readonly ICacheManager cacheManager;
private const string BanksAllCacheKey = "banks-all";
public BankRepository(IDatabaseFactory databaseFactory, ICacheManager cacheManager)
: base(databaseFactory)
Check.Argument.IsNotNull(cacheManager, "cacheManager");
this.cacheManager = cacheManager;
public IEnumerable<Bank> FindAll()
string key = string.Format(BanksAllCacheKey);
return cacheManager.Get(key, () =>
var query = from bank in DatabaseContext.Banks
orderby bank.Name
select bank;
return query.ToList();
);
我希望这会有所帮助。这是一个非常简单的实现,但它对我有用。 ASP.NET MVC
中有很多关于如何使用缓存策略的文章。就Google
吧。
【讨论】:
很好的答案。我很想使用这种方法。允许在开发人员想要时“清除缓存”的能力(我一直在为我的 [OutputCache] 属性与我的持续时间作斗争......如果你能在这个实现上放置一个持续时间,我会更喜欢它...... . 没关系,在这里回答我自己的问题:msdn.microsoft.com/en-us/library/… 很好,但是我不想在获取返回 null 、 0 或空 IEnumerable 时缓存,如何修复扩展方法?谢谢 你可以通过查看开源购物平台nopcommerce来清理,他们使用自己的CacheManager
,请查看他们的source和this的帖子,希望有所帮助.
MVCForum 也使用了 CacheManger,它在 Github 上是开源的。【参考方案3】:
在选择缓存实现之前,这里有几件事情需要考虑,但您必须决定的主要事情之一是您希望缓存在什么时候发生 - 在数据访问、模型创建或 UI 生成时?一个或所有这些地方?
您有多种选择,但对于一般数据缓存,您可以使用 System.Runtime.Caching.MemoryCache
,或者对于更灵活和更有价值的东西,您可以查看使用 NoSQL 的实现,例如 Redis。
您可以使用 MemoryCache
进行数据缓存,但使用 Redis 来缓存构成视图模型的聚合。如果您使用 Redis,您当然可以使用它来处理所有缓存。好处是您的所有数据将在应用程序重新启动时保持不变。缺点是它成为运行 CMS 的额外要求。
其他需要考虑的因素是一致性(使用一些 IoC 会有所帮助)并允许数据在更新后失效。因此有一些更新缓存的方法。
关于 最佳 方法,如果您正在创建一个新的 CMS 应用程序,请从小处/简单开始并逐步构建。您可能第一次无法做到完美,但只要您的方法始终如一且清晰,就应该很容易在您所做的基础上再接再厉,或者换掉并尝试不同/更好的东西。
【讨论】:
以上是关于如何缓存数据库表以防止在 Asp.net C# mvc 中出现许多数据库查询的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 数据库和 .NET (C#) - 如何防止 SQL 注入
在 Asp.net C# 中创建动态控件,并缓存控件并绑定数据
我的 asp.net mvc Web 应用程序中的 OutputCache 设置。防止缓存的多种语法