Last active
July 21, 2020 13:54
-
-
Save kudchikarsk/fea3ce276a591f86fd3d5ba74a6a6946 to your computer and use it in GitHub Desktop.
A extension class for asp.net web api developers. Extension methods for pagination, orderby properties, alpha pagination, and date range filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Core.Utils; | |
using System; | |
using System.Collections.Generic; | |
using System.Data.Entity; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Text.RegularExpressions; | |
using System.Threading.Tasks; | |
using System.Web; | |
namespace Logic.Utils | |
{ | |
public static class IQueryableExtensions | |
{ | |
public static IQueryable<T> WhereNameStartsWith<T>(this IQueryable<T> query, string selectedLetter) where T : class, IName | |
{ | |
if (String.IsNullOrWhiteSpace(selectedLetter)) return query; | |
if (selectedLetter == "0-9") | |
{ | |
var numbers = Enumerable.Range(0, 10).Select(i => i.ToString()); | |
return query = query.Where(p => numbers.Contains(p.Name.Substring(0, 1))); | |
} | |
return query.Where(e => e.Name.StartsWith(selectedLetter)); | |
} | |
public static IQueryable<T> WhereLike<T>(this IQueryable<T> query, string searchTerm,Func<string, Expression<Func<T, bool>>> predicate) where T : class | |
{ | |
searchTerm = searchTerm ?? ""; | |
var expressions = searchTerm.Split() | |
.Where(s => !String.IsNullOrWhiteSpace(s)) | |
.Select(s => s.Trim()) | |
.Select(e => "%" + searchTerm + "%") | |
.ToList(); | |
var idPattern = @"[1-9]\d+"; | |
var costCenterPattern = @"\S+[1-9]\d+"; | |
var costCenterMatch = Regex.Match(searchTerm, costCenterPattern); | |
if (costCenterMatch.Success && costCenterMatch.Value == searchTerm) | |
{ | |
var idMatch = Regex.Match(searchTerm, idPattern); | |
if (idMatch.Success) | |
{ | |
expressions.Clear(); | |
expressions.Add("%" + idMatch.Value + "%"); | |
} | |
} | |
foreach (var likeExpression in expressions) | |
{ | |
query = query.Where(predicate(likeExpression)); | |
} | |
return query; | |
} | |
public static IQueryable<T> FilterDeleted<T>(this IQueryable<T> query) where T: class, ISoftDelete | |
{ | |
return query.Where(e => !e.IsDeleted); | |
} | |
/// <summary> | |
/// Creates a paged set of results. | |
/// </summary> | |
/// <typeparam name="TEntity">The type of the source IQueryable.</typeparam> | |
/// <param name="queryable">The source IQueryable.</param> | |
/// <param name="page">The page number you want to retrieve.</param> | |
/// <param name="pageSize">The size of the page.</param> | |
/// <param name="orderBy">The field or property to order by.</param> | |
/// <param name="ascending">Indicates whether or not the order should be ascending (true) or descending (false.)</param> | |
/// <returns>Returns a paged set of results.</returns> | |
public static async Task<PagedResults<TEntity>> PaginateAsync<TEntity>( | |
this IQueryable<TEntity> dbQuery, | |
int page, | |
int pageSize | |
) | |
{ | |
var skipAmount = pageSize * (page - 1); | |
var projection = dbQuery | |
.Skip(skipAmount) | |
.Take(pageSize); | |
var totalNumberOfRecords = await dbQuery.CountAsync(); | |
var results = await projection.ToListAsync(); | |
var mod = totalNumberOfRecords % pageSize; | |
var totalPageCount = (totalNumberOfRecords / pageSize) + (mod == 0 ? 0 : 1); | |
return new PagedResults<TEntity> | |
{ | |
Results = results, | |
PageNumber = page, | |
PageSize = pageSize, | |
ResultCount = results.Count, | |
TotalNumberOfPages = totalPageCount, | |
TotalNumberOfRecords = totalNumberOfRecords, | |
}; | |
} | |
/// <summary> | |
/// Order the IQueryable by the given property or field. | |
/// </summary> | |
/// <typeparam name="T">The type of the IQueryable being ordered.</typeparam> | |
/// <param name="queryable">The IQueryable being ordered.</param> | |
/// <param name="propertyOrFieldName">The name of the property or field to order by.</param> | |
/// <param name="ascending">Indicates whether or not the order should be ascending (true) or descending (false.)</param> | |
/// <returns>Returns an IQueryable ordered by the specified field.</returns> | |
public static IQueryable<T> OrderByPropertyOrField<T>(this IQueryable<T> queryable, string propertyOrFieldName, bool ascending = true) | |
{ | |
var elementType = typeof(T); | |
var orderByMethodName = ascending ? "OrderBy" : "OrderByDescending"; | |
var parameterExpression = Expression.Parameter(elementType); | |
var propertyOrFieldExpression = GetMemberExpression(parameterExpression, propertyOrFieldName); | |
var selector = Expression.Lambda(propertyOrFieldExpression, parameterExpression); | |
var orderByExpression = Expression.Call(typeof(Queryable), orderByMethodName, | |
new[] { elementType, propertyOrFieldExpression.Type }, queryable.Expression, selector); | |
return queryable.Provider.CreateQuery<T>(orderByExpression); | |
} | |
public static IQueryable<T> BetweenDates<T>(this IQueryable<T> queryable, string propertyOrFieldName, DateTime? start, DateTime? end) | |
{ | |
var elementType = typeof(T); | |
var parameterExpression = Expression.Parameter(elementType); | |
var propertyOrFieldExpression = GetMemberExpression(parameterExpression, propertyOrFieldName); | |
var p = Expression.Convert(propertyOrFieldExpression, typeof(DateTime?)); | |
var notNullExpression = Expression.NotEqual(p, Expression.Constant(null, typeof(DateTime?))); | |
var startExp = Expression.Constant(start, typeof(DateTime?)); | |
var lessThan1 = Expression.LessThanOrEqual(startExp, p); | |
var endExp = Expression.Constant(end, typeof(DateTime?)); | |
var lessThan2 = Expression.LessThanOrEqual(p, endExp); | |
var and1 = Expression.And(notNullExpression, lessThan1); | |
var and2 = Expression.And(and1, lessThan2); | |
var whereClause = Expression.Lambda<Func<T, bool>>(and2, | |
new ParameterExpression[] { parameterExpression }); | |
var dateFilterExpression = Expression.Call(typeof(Queryable), "Where", | |
new[] { elementType }, queryable.Expression, whereClause); | |
return queryable.Provider.CreateQuery<T>(dateFilterExpression); | |
} | |
public static MemberExpression GetMemberExpression(Expression param, string propertyName) | |
{ | |
if (propertyName.Contains(".")) | |
{ | |
int index = propertyName.IndexOf("."); | |
var subParam = Expression.Property(param, propertyName.Substring(0, index)); | |
return GetMemberExpression(subParam, propertyName.Substring(index + 1)); | |
} | |
return Expression.Property(param, propertyName); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.