添加分页和过滤到典型的Linq规范模式?

时间:2010-12-23 14:16:58

标签: linq nhibernate asp.net-mvc-2 specification-pattern

我有一个大量使用网格的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完全提取所有记录,随着时间的推移,每个用户可以增长到数百条记录。这意味着大量低效的网络干扰。因此,显然,需要降低标准,以便NHibernate和Linq生成的SQL更好地过滤。

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的能力?

1 个答案:

答案 0 :(得分:0)

以下代码中对.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(); 
} 

您需要重构以删除它们并针对SQL对象的架构运行Dynamic LINQ,以便能够在服务器端进行过滤。