protected PaginationResult <TEntity> CreatePaginationResult(IQueryable <TEntity> query, IPageForm form, bool applyPagination)
        {
            var page = form.GetPage();
            var skip = form.GetSkip();
            var take = form.GetTake();

            if (Mode == PaginationMode.SkipAndTake)
            {
                int actualSkip = 0;
                if (skip.HasValue)
                {
                    actualSkip = skip.Value;
                }

                int actualTake = MaxTake;
                if (take.HasValue && take.Value < MaxTake)
                {
                    actualTake = MaxTake;
                }

                return(new PaginationResult <TEntity>(
                           actualSkip,
                           actualTake,
                           applyPagination ? query.Skip(actualSkip).Take(actualTake) : query));
            }
            else
            {
                var pageSize   = GetPageSize(form);
                int actualPage = 0;
                if (page.HasValue)
                {
                    actualPage = page.Value;
                }
                else if (skip.HasValue)
                {
                    actualPage = skip.Value / pageSize;
                }

                return(new PaginationResult <TEntity>(
                           actualPage * pageSize,
                           pageSize,
                           actualPage,
                           pageSize,
                           applyPagination ? query.Skip(actualPage * pageSize).Take(pageSize) : query));
            }
        }
Exemple #2
0
        public override PaginationResult <TEntity> ApplyPagination(IQueryable <TEntity> query, IPageForm form)
        {
            var filteringForm = form as IFilterForm;

            if (filteringForm == null)
            {
                throw new QuerySearchException("The IPageForm must also implement IFilterForm in order to support FtsQuerySearchProvider.");
            }

            var term = GetSearchExpression(filteringForm.GetTerm());

            if (!string.IsNullOrWhiteSpace(term))
            {
                // keep track of the untouched query
                var untouchedQuery = query;

                // apply where clause again (so we the outer query will be 'complete', and can simply replace what comes after the SELECT of the inner query)
                query = base.ApplyWhere(query, filteringForm);

                // if we are not sorting by the term, we should simply use the default mechanism
                bool isAlreadySorted = false;
                if (!form.SortByTermRank())
                {
                    isAlreadySorted = true;

                    var result = base.ApplyPagination(query, form);
                    query = result.Query;
                }

                // get the sql of the query (WHERE + JOIN + ORDER BY, etc.)
                var sql = query.ToSql();

                // create a reader for our sql, and a builder to build a new query
                var reader  = new StringReader(sql);
                var builder = new StringBuilder();

                // variable to keep track of the alias used for the table in the outer query
                string usedAlias = string.Empty;

                // variable to keep track of whether or not the sql line we are iterating should be part of the new sql statement
                bool iteratingRelevantSql = false;

                string line = null;
                while ((line = reader.ReadLine()) != null)
                {
                    if (line == "FROM (")
                    {
                        // read our base query
                        var baseQuery = reader.ReadLine();
                        builder.AppendLine(baseQuery);

                        // this line marks the start of the sub query
                    }
                    else if (line.StartsWith(") AS "))
                    {
                        // this line marks the start of WHERE/ORDER BY/WHATEVER of the outer query
                        usedAlias = line.Substring(5);

                        iteratingRelevantSql = true;
                    }
                    else if (iteratingRelevantSql)
                    {
                        builder.AppendLine(line);
                    }
                }

                // if we have NOT already appended a OFFSET/FETCH query part, do that now
                if (!isAlreadySorted)
                {
                    // calculate fetch and offset
                    int fetch  = 0;
                    int offset = 0;

                    var page = form.GetPage();
                    var skip = form.GetSkip();
                    var take = form.GetTake();
                    if (Mode == PaginationMode.SkipAndTake)
                    {
                        if (skip.HasValue)
                        {
                            offset = skip.Value;
                        }
                        int actualTake = MaxTake;
                        if (take.HasValue && take.Value < MaxTake)
                        {
                            fetch = MaxTake;
                        }
                    }
                    else
                    {
                        var pageSize   = GetPageSize(form);
                        int actualPage = 0;
                        if (page.HasValue)
                        {
                            actualPage = page.Value;
                        }
                        else if (skip.HasValue)
                        {
                            actualPage = skip.Value / pageSize;
                        }

                        offset = actualPage * pageSize;
                        fetch  = pageSize;
                    }

                    // we have NOT ordered sql, which means that we need to do it based on the term
                    builder.AppendLine(CreateOrderBy(offset, fetch));
                }

                // calculate the final sql and use it as the base on the untouched query
                var rawSql = builder.Replace(usedAlias, TableAlias).ToString();

                // parameterize the final sql
                int    parameterStart = rawSql.IndexOf(", N'") + 2;
                int    parameterEnd   = rawSql.IndexOf("' ) AS") + 1;
                string parameter      = rawSql.Substring(parameterStart, parameterEnd - parameterStart);

                var finalSql = rawSql.Replace(parameter, "{0}");
                return(CreatePaginationResult(untouchedQuery.FromSql(finalSql, term), form, false));
            }
            else
            {
                return(base.ApplyPagination(query, form));
            }
        }