我正在尝试找到一种“缓存”以下查询的方法,因为它的编译增加了我的总渲染时间(这在ASP.NET MVC 5中使用EF 6.1)从<50ms到~700ms:
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”组合,并且只要请求两种文化就不会返回任何内容。
目前我使用以下内容,这给了我&lt; 50ms渲染时间,但对我来说似乎是“hacky”:
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缓存?
我真的不关心〜第一次点击的~700ms“,但这个查询几乎每一页都会执行(因为它加载页面的文本内容) - 有时甚至多次 - 并且会减少整个网站表现显着......
P.S。:我也愿意把查询写得完全不同
我得到一个IQueryable<T>
的项目和带有文化的列表来获取每个项目。然后,我需要文化要求的每个项目的最新版本。
多种文化实际上仅用作“后备” - 所以,如果我得到{ "de-AT", "de", "en" }
,我首先搜索结果以获得de-AT
的修订,然后de
,最后en
并返回找到的第一个。
如果这已经可以“在数据库中”完成,那将是完美的,但我不知道如何在SQL中工作(“文化树”也保存在数据库中并在其他地方查询/缓存,因此它可能是“接合“)。
答案 0 :(得分:1)
现在我使用LINQkit解决了它,但我仍然希望能够使用Contains
:
var revisions = itemQuery.SelectMany(i => i.Revisions
.Where(r => r.State == ContentRevisionState.Published).OfType<R>());
revisions = revisions.ForList(cultures,
(p, c) => p.Or(r => r.CultureCode == c.CultureCode));
revisions = revisions.OrderByDescending(r => r.Culture.Position)
.ThenByDescending(r => r.DateCreated)
.Include(r => r.Author).Include(r => r.Culture);
var revision = await revisions.FirstOrDefaultAsync();
和
public static IQueryable<T> ForList<T, K>(this IQueryable<T> items, List<K> list,
Func<Expression<Func<T, bool>>, K, Expression<Func<T, bool>>> condition)
{
var predicate = PredicateBuilder.False<T>();
foreach (var item in list)
{
var tmp = item; // local copy for deferred execution
predicate = condition(predicate, tmp);
}
return items.AsExpandable().Where(predicate);
}
答案 1 :(得分:0)
修改强>:
您可能想要预编译查询。有关预编译查询的更多信息:
http://msdn.microsoft.com/en-us/magazine/ee336024.aspx
您只需将查询存储在静态变量中:
private static var query = 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);
然后每次调用它以获得结果而不会导致重新编译:
var revisions = query.FirstOrDefault();
您可以使用此机制获得相同的内容:
private static var query = null;
...
...
if (query == null)
{
query = ... // initialize it here
}
这样,您也不需要所有引用都是静态的。