1

いくつかのレコードをページングしたいのですが、Take()拡張機能からLINQ期待した結果が返されません。

public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end)
{
  return dbcontext.Persons.Where(x => x.RegisterDate >= start && x.RegisterDate <= end).Take(20);
}

このメソッドを再度実行すると、同じ結果が得られます。正確にはどのように機能しTake()ますか?

4

2 に答える 2

6

このTakeメソッドは、最初の N レコード (N はパラメーター)、または合計が N 未満の場合はすべてのレコードを返します。ページングを実装するには、 と組み合わせて使用​​しSkip、結果の次のページを取得する前にスキップするレコード数を指定します。クエリが毎回同じ順序で結果を返すように、全体的な順序を指定することもできます。

注: ゼロベースのページングを想定しています。

private const int _pageSize = 20;

public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end, int? page)
{
     return dbcontext.Persons
                     .Where(x => x.RegisterDate >= start && x.RegisterDate <= end)
                     .OrderBy(x => x.LastName)
                     .ThenBy(x => x.FirstName)
                     .ThenBy(x => x.Id) // using unique id to force consistent total order
                     .Skip((page ?? 0) * _pageSize)
                     .Take(_pageSize);
}
于 2013-09-07T21:33:22.233 に答える
5

.Takeクエリで指定された数の結果を返します。同じクエリであれば、多くの場合、同じ結果が返されます。これを解決するには、 と を組み合わせて使用​​し、.Skip毎回pingおよびing する.Take番号を変更します。SkipTake

private int counter = 0;
public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end)
{
    var results = dbcontext.Persons.Where(x => x.RegisterDate >= start && x.RegisterDate <= end).Skip(counter).Take(20);
    counter += 20;
    return results;
}

レコードがなくなった後でも、これを継続的に呼び出すことができることに注意してください。

または、クエリをキャッシュすることもできます (使用するたびにクラスを再インスタンス化しない場合)。

private IQueryable<Person> qry = dbcontext.Persons.Where(x => x.RegisterDate >= start && x.RegisterDate <= end);
public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end)
{
    qry = qry.Skip(20);
    return qry.Take(20);
}

それにもかかわらず、これらのスニペットの両方に他の問題がある可能性があります - tvanfosson のコメントと回答を参照してください。

于 2013-09-07T21:27:29.677 に答える