实体框架灵活缓存
本文关键字:缓存 框架 实体 | 更新日期: 2023-09-27 17:58:10
我正在寻找一个能与Entity Framework 6+一起工作的缓存系统。要么找到一个合适的库,要么自己实现。
我已经调查了这两个开源缓存提供商:
实体框架6.1的二级缓存https://efcache.codeplex.com/
EFSecondLevelCachehttps://github.com/VahidN/EFSecondLevelCache/
它们看起来像是可靠的产品,尽管我正在寻找一种方法来指定查询中的最大缓存时间。我认为这将是指定我能够接受的最旧数据的最佳方式(因为这当然非常依赖于业务逻辑)
我认为这将是最好的称呼方式:
using (var db = new MyEF6Entities()) {
var path = db.Configuration.Where(c => c.name="Path")
.AllowFromCache(TimeSpan.FromMinutes(60));
var onlineUserList = db.Users.Where(u => u.IsOnline)
.AllowFromCache(TimeSpan.FromSeconds(30));
}
有没有办法制作这样的API?
编辑:我现在已经按照@JonathanMagnan的建议尝试了EF+,但作为一个例子,下面的代码从来没有缓存命中。我知道这一点是因为它非常慢,我还在mysql管理员中看到与特定查询建立了连接,如果我更改数据库中的数据,它将立即显示,我预计会延迟60分钟
public String GetClientConfig(string host, Guid deviceId) {
using (var db = new DbEntities(host)) {
var clientConfig = db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60)).ToList();
return string.Join("'n", clientConfig.Select(b => b.Name + "=" + b.Value));
}
return null;
}
编辑2:我意识到缓存不起作用,但它仍然会创建到数据库的连接,因为我创建了一个新的上下文实例。但是有一个问题!我在网络服务中处理EF请求。根据web服务的主机名host:-header,将查询不同的数据库。EF Plus似乎无法处理此问题,因此如果我使用http://host1/ClientConfig我后来从http://host2/ClientConfig.有没有办法用主机名标记缓存
免责声明:我是项目Entity Framework Plus(EF+)的所有者
我不能代表你已经调查过的其他库,但EF+QueryCache允许在特定的时间内缓存数据。
Wiki:EF+查询缓存
示例
using (var db = new MyEF6Entities()) {
var path = db.Configuration.Where(c => c.name="Path")
.FromCache(DateTime.Now.AddMinutes(60));
var onlineUserList = db.Users.Where(u => u.IsOnline)
.FromCache(DateTime.Now.AddSeconds(30));
}
如果某些逻辑需要实时数据,而其他逻辑不需要,您也可以使用缓存"标签"多次缓存数据
示例
using (var db = new MyEF6Entities()) {
var recentUserList = db.Users.Where(u => u.IsOnline)
.FromCache(DateTime.Now.AddHours(1), "recent");
var onlineUserList = db.Users.Where(u => u.IsOnline)
.FromCache(DateTime.Now.AddSeconds(30), "online");
}
据我所知,我认为任何缓存支持都不会占用最后X秒内缓存的数据。
编辑:回答子问题
谢谢乔纳森。EF+如何使用不同的数据库例如,以及不同的登录用户。它能处理吗这是自动的,还是我需要给它一些提示?
它取决于每个功能。例如,查询缓存适用于所有数据库提供程序,因为后台只使用LINQ。您不需要指定任何内容,它已经处理了所有内容。
其他一些功能,如Query Future,还不能在所有提供者上运行。它适用于SQL Server、SQL Azure和MySQL等流行的提供商。
您可以在每个功能下面看到需求部分。如果它支持所有提供商,我们通常会说"All supported"。
编辑:回答子问题
我在MyEF6Entitys构造函数中更改了数据库,所以问题是如果EF+将考虑数据库名称,或者这可能会造成混乱向上缓存?
从v1.3.34开始,连接字符串现在是密钥的一部分。因此,这将支持这种情况。
密钥由以下部分组成:
- 缓存前缀
- 连接字符串
- 所有缓存标记
- 所有参数名称&值
有没有办法用主机名标记缓存
您可以使用缓存标签:EF+查询缓存标签&过期标签
示例:
var host1 = "http://host1/ClientConfig";
var host2 = "http://host2/ClientConfig";
var clientHost1 = db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60), host1).ToList();
var clientHost1 = db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60), host2).ToList();
所有标记都是缓存键的一部分,因此两个查询都将缓存在不同的缓存条目中。
编辑:回答子问题
我在MyEF6Entity()构造函数中设置了ConnectionString似乎仍然混淆了来自不同数据库的数据
你能生成缓存密钥并检查是否包括连接字符串吗?
var query = b.Users.Where(u => u.IsOnline);
var cacheKey = QueryCacheManager.GetCacheKey(query, new string[0]);
如果我这样做(例如var clientHost),它就会起作用=数据库。客户端配置。FromCache(DateTime.Now.AddMinutes(60),hostName)。ToList();但我不应该这么做,因为connectionString不同,对吧?
是的,你是对的。如果连接字符串随主机而更改,则不需要它。