/// <summary> /// Gets the sorting to be used. /// </summary> /// <returns></returns> public static IEnumerable <SortMemberAccess> GetSorting(this IPageForm form, ParameterExpression parameter) { if (!string.IsNullOrWhiteSpace(form.GetOrderBy())) { return(ExpressionHelper.CalculateSortMemberAccesses(parameter, form.GetOrderBy())); } return(null); }
protected int GetPageSize(IPageForm form) { switch (Mode) { case PaginationMode.PageSize: return(PageSize); case PaginationMode.PredefinedPageSizes: var pageSize = form.GetPageSize(); if (!pageSize.HasValue) { throw new QuerySearchException("No page size has been specified in the query."); } if (!PredefinedPageSizes.Contains(pageSize.Value)) { throw new QuerySearchException("The specified page size is not allowed."); } return(pageSize.Value); case PaginationMode.AnyPageSize: return(form.GetPageSize() ?? PageSize); case PaginationMode.MinMaxPageSize: var ps = form.GetPageSize(); if (!ps.HasValue) { throw new QuerySearchException("No page size has been specified in the query."); } if (ps < MinPageSize || ps > MaxPageSize) { throw new QuerySearchException("Invalid page size was specified."); } return(ps.Value); default: throw new QuerySearchException($"Invalid PaginationMode configured: {Mode}."); } }
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)); } }
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)); } }
/// <summary> /// Applies the pagination form to the query. /// </summary> /// <param name="query">The query that should be paginated.</param> /// <param name="form">The pagination form that should be applied to the query.</param> /// <returns>A pagination result.</returns> public virtual PaginationResult <TEntity> ApplyPagination(IQueryable <TEntity> query, IPageForm form) { var sorting = form.GetSorting(_parameter)?.ToList(); var alreadySortedByPropertyPaths = new List <string>(); if (sorting != null && sorting.Count > 0) { // first order by user specified sorting bool isSorted = false; foreach (var sort in sorting) { if (sort.MemberAccessor != null) { query = query.OrderBy(_parameter, sort, isSorted); } else { query = ApplyManualOrdering(query, sort.PropertyPath, sort.SortDirection, isSorted); } isSorted = true; alreadySortedByPropertyPaths.Add(sort.PropertyPath); } query = ApplyUniqueSort(alreadySortedByPropertyPaths, (IOrderedQueryable <TEntity>)query); } else { query = ApplyDefaultSort(alreadySortedByPropertyPaths, query); query = ApplyUniqueSort(alreadySortedByPropertyPaths, (IOrderedQueryable <TEntity>)query); } return(CreatePaginationResult(query, form, true)); }
/// <summary> /// Applies the pagination form to the query. /// </summary> /// <param name="query">The query that should be paginated.</param> /// <param name="form">The pagination form that should be applied to the query.</param> /// <returns>A pagination result.</returns> public virtual PaginationResult <TEntity> ApplyPagination(IQueryable <TEntity> query, IPageForm form) { bool isSorted = false; var sorting = form.GetSorting(_parameter)?.ToList(); if (sorting != null && sorting.Count > 0) { // first order by user specified sorting query = query.OrderBy(_parameter, sorting); isSorted = true; if (_uniqueSort != null) { query = ApplyOrdering(query, _uniqueSort, _uniqueSortDirection, ref isSorted); } else if (_defaultSort != null) { query = ApplyOrdering(query, _defaultSort, _defaultSortDirection, ref isSorted); } } else { // first order by default sorting if (_defaultSort != null) { query = ApplyOrdering(query, _defaultSort, _defaultSortDirection, ref isSorted); } // then order by unique sorting, if present, and not equal to unique sorting if (_uniqueSort != null) { if (!(ReferenceEquals(_uniqueSort, _defaultSort) && _uniqueSortDirection == _defaultSortDirection)) { query = ApplyOrdering(query, _uniqueSort, _uniqueSortDirection, ref isSorted); } } } return(CreatePaginationResult(query, form, true)); }
/// <summary> /// Applies the pagination form to the query. /// </summary> /// <param name="query">The query that should be paginated.</param> /// <param name="form">The pagination form that should be applied to the query.</param> /// <returns>A pagination result.</returns> public virtual PaginationResult <TEntity> ApplyPagination(IQueryable <TEntity> query, IPageForm form) { var sorting = form.GetSorting(_parameter)?.ToList(); var alreadySortedByPropertyPaths = new List <string>(); if (sorting != null && sorting.Count > 0) { // first order by user specified sorting query = query.OrderBy(_parameter, sorting); alreadySortedByPropertyPaths.AddRange(sorting.Select(x => x.PropertyPath)); query = ApplyUniqueSort(alreadySortedByPropertyPaths, (IOrderedQueryable <TEntity>)query); } else { query = ApplyDefaultSort(alreadySortedByPropertyPaths, query); query = ApplyUniqueSort(alreadySortedByPropertyPaths, (IOrderedQueryable <TEntity>)query); } return(CreatePaginationResult(query, form, true)); }