Paging in servicestack ormlite
Asked Answered
P

2

12

I am looking for a good way to implement paging in ormlite and I found another question, which has this snippet:

var data = db.Select<address>(predicate).Skip((int) pageNumber).Take((int) pageSize).ToList();

Problem with the above is that it gets back all the results and then does the skip and take on it which defeats the purpose of paging.

At another google groups post I have found the same problem and a sample in a github issue is mentioned as a solution but the URL no longer works. Does anyone know how to correctly page using servicestack?

Pallium answered 16/9, 2013 at 9:34 Comment(0)
P
30

Found the answer in ormlite's tests. Essentially we could use SqlExpressionVisitor's Limit() like this:

var result = db.Select<K>( q => q.Where(predicate).Limit(skip:5, rows:10 ) );

Pallium answered 16/9, 2013 at 10:16 Comment(0)
I
3

I built a higher-level wrapper if you prefer working with Page and PageSize:

public static class PagingExtensions
{
    public static SqlExpression<T> Page<T>(this SqlExpression<T> exp, int? page, int? pageSize)
    {
        if (!page.HasValue || !pageSize.HasValue)
            return exp;

        if (page <= 0) throw new ArgumentOutOfRangeException("page", "Page must be a number greater than 0.");
        if (pageSize <= 0) throw new ArgumentOutOfRangeException("pageSize", "PageSize must be a number greater than 0.");

        int skip = (page.Value - 1) * pageSize.Value;
        int take = pageSize.Value;

        return exp.Limit(skip, take);
    }

    // https://mcmap.net/q/352077/-how-to-force-a-number-to-be-in-a-range-in-c-duplicate
    public static int? LimitToRange(this int? value, int? inclusiveMinimum, int? inclusiveMaximum)
    {
        if (!value.HasValue) return null;
        if (inclusiveMinimum.HasValue && value < inclusiveMinimum) { return inclusiveMinimum; }
        if (inclusiveMaximum.HasValue && value > inclusiveMaximum) { return inclusiveMaximum; }
        return value;
    }
}

Then you can write your query as:

var results = Db.Select<K>(predicate.Page(request.Page, request.PageSize));

Or, using the additional helper method to keep Page and PageSize to sensical and (possibly) performant values:

var results = Db.Select<K>(predicate.Page(request.Page.LimitTo(1,null) ?? 1, request.PageSize.LimitTo(1,100) ?? 100);

Which will enforce reasonable limits on Page and PageSize

Irwinirwinn answered 25/1, 2016 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.