У меня есть приложение 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();
Но вся фильтрация происходит на среднем уровне с полным извлечением всех записей по идентификатору пользователя, который со временем может вырасти до сотен записей на пользователя. Это означает много неэффективной сетевой болтовни. Таким образом, очевидно, что нужно понизить критерии, чтобы 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, например, имеет MatchingCriteria:
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?
Skip()
иTake()
в результирующем SQL-запросе. - person mmix   schedule 15.03.2011