我正在寻找与Entity Framework 6+兼容的缓存系统。要么找到合适的图书馆,要么自己实施。
我已经调查了这两个开源缓存提供程序:
实体框架6.1的二级缓存 https://efcache.codeplex.com/
EFSecondLevelCache https://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:我意识到缓存不起作用,但它仍然创建了与数据库的连接,因为我创建了一个新的上下文实例。但是有一个问题!我在Web服务中执行EF请求。根据Web服务主机的主机名:-header查询不同的数据库。 EF Plus似乎没有处理这个,所以如果我使用http://host1/ClientConfig我后来得到http://host2/ClientConfig相同且不正确的结果。有没有办法用主机名标记缓存?
答案 0 :(得分:2)
免责声明:我是该项目的所有者Entity Framework Plus (EF+)
我不能代表您已调查过的其他库,但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才能使用。您不需要指定任何内容,它已经处理了所有内容。
“查询未来”等其他一些功能尚未在所有提供商上运行。它适用于SQL Server,SQL Azure和MySQL等流行的提供程序。
您可以在每个功能下看到要求部分。如果支持所有提供商,我们通常会说“全部支持”。
编辑:回答子问题
我在MyEF6Entities构造函数中更改数据库,所以问题是 如果EF +将考虑数据库名称或如果这可能会弄乱 缓存?
从v1.3.34开始,连接字符串现在是密钥的一部分。所以这将支持这种情况。
密钥由:
组成有没有办法用主机名
标记缓存
您可以使用缓存标记:EF+ Query Cache Tag & ExpireTag
示例:
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();
所有标记都是缓存键的一部分,因此两个查询都将缓存在不同的缓存条目中。
编辑:回答子问题
我在MyEF6Entities()构造函数中设置了ConnectionString 仍然似乎混淆了来自不同数据库的数据
您是否可以生成缓存密钥并检查是否包含连接字符串?
var query = b.Users.Where(u => u.IsOnline);
var cacheKey = QueryCacheManager.GetCacheKey(query, new string[0]);
如果我做例如var clientHost =,它可以工作 db.ClientConfig.FromCache(DateTime.Now.AddMinutes(60), 主机名).ToList();但是我不需要这样做 connectionStrings是不同的,对吧?
是的,你是对的。如果连接字符串随主机一起变化,则不应该需要它。