【发布时间】:2014-08-07 21:06:47
【问题描述】:
我正在尝试找到一种“缓存”以下查询的方法,因为它的编译将我的总渲染时间(这在 EF 6.1 的 ASP.NET MVC 5 中使用)从
var revisions = from i in items
from r in i.Revisions
where cultures.Contains(r.Culture.CultureCode)
group r by new { r.ItemId, r.Culture } into g
select g.OrderByDescending(r => r.DateCreated).FirstOrDefault();
cultures 目前是 List<string>,通常包含 1-3 个项目。
据我了解,IEnumerable.Contains 无法缓存,因为在编译时长度未知,但我也尝试使用没有帮助的数组。
更新:以下查询是错误的,因为它会进行“AND”组合,并且在请求两种文化时不返回任何内容。目前我使用以下,这给了我
var revisions = items.SelectMany(i => i.Revisions);
foreach (var culture in cultures)
revisions = revisions.Where(r => r.Culture.CultureCode == culture);
var result = from r in revisions
group r by new { r.ItemId, r.Culture } into g
select g.OrderByDescending(r => r.DateCreated).FirstOrDefault();
有没有办法在不“构建自定义查询”的情况下获得相同的结果?
有没有办法编写这个查询以便它被 EF 缓存?
我并不真正关心“第一次点击”大约 700 毫秒,但这个查询几乎在每个页面上执行(因为它加载页面的文本内容) - 有时甚至多次 - 并且会减少整体网站性能显着...
P.S.:我也愿意写完全不同的查询。
我得到一个带有项目的IQueryable<T> 和包含每个项目的文化的列表。然后,我需要文化要求的每个项目的最新版本。
多种文化实际上仅用作“后备” - 所以如果我得到{ "de-AT", "de", "en" },我会先搜索结果以查找带有de-AT的修订版,然后是de,最后是en并返回找到第一个。
如果这已经可以“在数据库中”完成,那将是完美的,但我不知道它如何在 SQL 中工作(“文化树”也保存在数据库中并在其他地方查询/缓存,所以它可能是“加入”)。
【问题讨论】:
-
为什么要挑出 Contains()?其余的也不缓存。
-
@HenkHolterman:因为这是原因(AFAIK EF 确实在内部缓存了它) - 如果我删除
Contains它也是 -
你没有在 MVC 中保持上下文打开是吗?
-
@HenkHolterman:不——
DbContext在它自己的using块中用于每个请求。但是没有ContainsEF 正在缓存“已编译的 LINQ 查询”,但没有... -
如果查询 w/o Contains 足够快,然后添加
.ToList().Contains(...)
标签: c# performance linq entity-framework ienumerable