2

我有一个大量使用网格的 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 的能力吗?

4

1 回答 1

0

以下代码中对 .ToList() 的调用导致在应用动态 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 对象的架构运行动态 LINQ,以便能够在服务器端进行过滤。

于 2011-03-17T06:53:35.433 回答