У меня есть приложение ASP.NET MVC2, которое интенсивно использует сетки. Я хотел бы посмотреть, есть ли способ добавить эффективные подкачку и фильтрацию к типичному шаблону спецификации.
По сути, вызов, с которого все начинается, выглядит так:
PatientByUserIdSpecification spc = new PatientByUserIdSpecification(userId);
return this.patientRepository.FindAll(spc).ToList();
Теперь я знаю, что могу сделать что-то подобное ниже и получить подмножество строк в зависимости от настроек сетки для подкачки и фильтрации:
return this.patientRepository.FindAll(spc).OrderBy(a => a.Id).Skip(start).Take(limit).ToList();
Но вся фильтрация происходит на среднем уровне с полным извлечением всех записей по userId, которое со временем может вырасти до сотен записей на пользователя. Это означает много неэффективного сетевого общения. Таким образом, очевидно, что необходимо отбросить критерии так, чтобы SQL, сгенерированный фильтрами NHibernate и Linq, был лучше.
Код LinqRepository в основном:
public IQueryable<T> FindAll(ILinqSpecification<T> specification)
{
return specification.SatisfyingElementsFrom(this.Session.Linq<T>());
}
public virtual IQueryable<TResult> SatisfyingElementsFrom(IQueryable<T> candidates)
{
if (this.MatchingCriteria != null)
{
return candidates.Where(this.MatchingCriteria).ToList().ConvertAll(this.ResultMap).AsQueryable();
}
return candidates.ToList().ConvertAll(this.ResultMap).AsQueryable();
}
И спецификация PatientByUserIdSpecification, например, имеет критерии соответствия:
public override Expression<Func<Patient, bool>> MatchingCriteria
{
get { return p => p.Cases.Any(c => c.CaseUsers.Any(x => (x.User.Id == this.userId))); }
}
Я думал, что с нижеследующим будет делать это, но запрос все еще слишком широк.
public virtual IQueryable<TResult> SatisfyingElementsFrom(IQueryable<T> candidates, int start, int limit, string sort, string dir)
{
if (this.MatchingCriteria != null)
{
return candidates.Where(this.MatchingCriteria).Skip(start).Take(limit).ToList().ConvertAll(this.ResultMap).AsQueryable();
}
return candidates.ToList().ConvertAll(this.ResultMap).AsQueryable();
}
Можно и как настроить возможность генерировать более качественный SQL?