У меня есть пара выражений, для которых я запускаю Count() в EF6. Сгенерированный SQL-запрос оказывается несколько сложным, затрагивая несколько таблиц с несколькими переданными параметрами. Однако он выполняется менее чем за секунду, если я скопирую SQL в SSMS.
В EF Linq Query занимает более 30 секунд и часто просто выдает исключение Connection Timeout.
Глядя на монитор активности, я вижу, что один и тот же запрос выполняется много тысяч (если не миллионов) раз.
Код, запускающий запросы, состоит из пары выражений, объединенных с помощью LinqKit AsExpandable() и Invoke().
//properties is an IQueryable<Property> and checkDate a DateTime
int propertyCount = FilterCompliantOnDate(properties, checkDate).Count();
public IQueryable<Property> FilterCompliantOnDate(IQueryable<Property> properties, DateTime checkDate)
{
// SelectedComplianceCategory is a local property (int?)
return properties.AsExpandable().Where(p=>PropertyIsCompliant.Invoke(p, checkDate, SelectedComplianceCategory));
}
public static readonly Expression<Func<Property, DateTime, int?, bool>> PropertyIsCompliant = (p, checkDate, complianceCategory) =>
CategoryComplianceRatings.Invoke(p, complianceCategory, checkDate).Any() &&
CategoryComplianceRatings.Invoke(p, complianceCategory, checkDate)
.All(cr => cr.ComplianceRating == ComplianceRating.Compliant);
private static readonly Expression<Func<Property, int?, DateTime, IQueryable<PropertyComplianceRating>>> CategoryComplianceRatings =
(p, categoryId, checkTime) => p.ComplianceRatings.AsQueryable()
.Where(cr =>
cr.ComplianceCategory != null &&
(
categoryId == null ||
(categoryId != null && cr.ComplianceCategory.Id == categoryId)
)
)
.GroupBy(cr => cr.ComplianceCategory)
.Select(g => g
.Where(cr => cr.Date < checkTime)
.OrderByDescending(cr => cr.Date)
.FirstOrDefault()
);