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オブジェクトのスキーマに対してDynamicLINQを実行する必要があります。

于 2011-03-17T06:53:35.433 に答える