Добавление подкачки и фильтрации в типичный шаблон Linq Specification? - PullRequest
2 голосов
/ 23 декабря 2010

У меня есть приложение 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?

1 Ответ

0 голосов
/ 17 марта 2011

Вызовы .ToList () в следующем коде вызывают выполнение запроса перед применением Dynamic LINQ:

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(); 
} 

Вам потребуется рефакторинг, чтобы удалить их и запустить Dynamic LINQ для схемы объектов SQL, чтобы иметь возможность фильтрации на стороне сервера.

...