private static IQueryable <T> ApplyWhere <T>(this IQueryable <T> source, string propertyName, object propertyValue) where T : class { // 1. Retrieve member access expression var mba = PropertyAccessorCache <T> .Get(propertyName); if (mba == null) { var ex = new NullReferenceException(); Log.Error(ex, $"Error when trying to get the property, it doesn't exist"); throw ex; } // 2. Try converting value to correct type object value; try { value = Convert.ChangeType(propertyValue, mba.ReturnType); } catch (SystemException ex) when( ex is InvalidCastException || ex is FormatException || ex is OverflowException || ex is ArgumentNullException) { Log.Error(ex, $"Error when trying to convert type of property value with type of property"); throw; } // 3. Construct expression tree var eqe = Expression.Equal( mba.Body, Expression.Constant(value, mba.ReturnType)); var expression = Expression.Lambda(eqe, mba.Parameters[0]); // 4. Construct new query MethodCallExpression resultExpression = Expression.Call( null, GetMethodInfo(Queryable.Where, source, (Expression <Func <T, bool> >)null), new Expression[] { source.Expression, Expression.Quote(expression) }); return(source.Provider.CreateQuery <T>(resultExpression)); }
public static IQueryable <T> Where <T>(this IQueryable <T> source, string propertyName, object propertyValue, out bool success) where T : class { success = false; var mba = PropertyAccessorCache <T> .Get(propertyName); if (mba == null) { return(source); } object value; try { value = Convert.ChangeType(propertyValue, mba.ReturnType); } catch (SystemException ex) when(ex is InvalidCastException || ex is FormatException || ex is OverflowException || ex is ArgumentNullException) { return(source); } var eqe = Expression.Equal(mba.Body, Expression.Constant(value, mba.ReturnType)); var queryExpr = Expression.Lambda(eqe, mba.Parameters[0]); success = true; var resultExpression = Expression.Call(null, GetMethodInfo <IQueryable <T>, Expression <Func <T, bool> >, IQueryable <T> >(Queryable.Where), new[] { source.Expression, Expression.Quote(queryExpr) }); return(source.Provider.CreateQuery <T>(resultExpression)); }
/// <summary> /// Get paging /// </summary> /// <returns></returns> /// created by: ntkien 02.06.2020 public virtual async Task <PagingResult <T> > GetByPaging() { List <T> results = null; int totalCounts = 0; using (NorthWindContext <T> context = new NorthWindContext <T>()) { IQueryable <T> query = context.ListBase; IQueryable <T> resultQuery = context.ListBase; if (_PagingObject == null) { return(null); } if (_PagingObject.WhereInfos != null && _PagingObject.WhereInfos.Count > 0) { foreach (WhereObject whereObject in _PagingObject.WhereInfos) { //ntkien: nếu là toán tử bettween thì sẽ apply where 2 lần if (whereObject.Operation == ExpressionOperationEnum.Bettween) { query = query.ApplyWhere(whereObject.ColumnName, whereObject.Value, whereObject.ColumnType, ExpressionOperationEnum.GreatThanEqual); query = query.ApplyWhere(whereObject.ColumnName, whereObject.Value2, whereObject.ColumnType, ExpressionOperationEnum.LessThanEqual); } else { query = query.ApplyWhere(whereObject.ColumnName, whereObject.Value, whereObject.ColumnType, whereObject.Operation); } } } if (_PagingObject.OrderInfos != null && _PagingObject.OrderInfos.Count > 0) { bool isFirst = true; foreach (OrderByObject orderByObject in _PagingObject.OrderInfos) { string sort = orderByObject.SortOperation; if (!string.IsNullOrWhiteSpace(sort) && sort.Equals("desc", StringComparison.OrdinalIgnoreCase)) { if (isFirst) { query = query.ApplyOrderByDesc(orderByObject.ColumnName); } else { query = query.ApplyThenByDesc(orderByObject.ColumnName); isFirst = false; } } else { if (isFirst) { query = query.ApplyOrderBy(orderByObject.ColumnName); } else { query = query.ApplyThenBy(orderByObject.ColumnName); isFirst = false; } } } } //ntkien 04.06.2020 lấy tổng số bản ghi totalCounts = await query.CountAsync(); if (_PagingObject.Skip >= 0) { query = query.Skip(_PagingObject.Skip).Take(_PagingObject.Take); } //ntkien 04.06.2020 nếu khóa chính ko truyền vào thì lấy theo định dạng EntityName + Id T t = new T(); var primayKey = Utility.GetPrimaryKeyName(t); if (string.IsNullOrWhiteSpace(primayKey)) { primayKey = _PagingObject.PrimaryKey; if (string.IsNullOrWhiteSpace(primayKey)) { primayKey = string.Format("{0}Id", t.GetType().Name); } } var x = Expression.Parameter(typeof(T), "x"); var body = Expression.PropertyOrField(x, primayKey); var lambda = Expression.Lambda <Func <T, Guid> >(body, x); //ntkien 04.06.2020 lấy ra danh sách id rồi mới lấy ra đầy đủ bản ghi (mục đích dùng để tối ưu) var ids = await query.Select(lambda).ToListAsync(); if (ids != null && ids.Count > 0) { Expression expressions = null; var mba = PropertyAccessorCache <T> .Get(primayKey); Expression eqe; foreach (object id in ids) { eqe = Expression.Equal(mba.Body, Expression.Constant(id, mba.ReturnType)); if (expressions == null) { expressions = eqe; } else { expressions = Expression.OrElse(expressions, eqe); } } var expression = Expression.Lambda(expressions, mba.Parameters[0]); // 4. Construct new query MethodCallExpression resultExpression = Expression.Call( null, Utility.GetMethodInfo(Queryable.Where, resultQuery, (Expression <Func <T, bool> >)null), new Expression[] { resultQuery.Expression, Expression.Quote(expression) }); resultQuery = resultQuery.Provider.CreateQuery <T>(resultExpression); if (_PagingObject.OrderInfos != null && _PagingObject.OrderInfos.Count > 0) { bool isFirst = true; foreach (OrderByObject orderByObject in _PagingObject.OrderInfos) { string sort = orderByObject.SortOperation; if (!string.IsNullOrWhiteSpace(sort) && sort.Equals("desc", StringComparison.OrdinalIgnoreCase)) { if (isFirst) { resultQuery = resultQuery.ApplyOrderByDesc(orderByObject.ColumnName); } else { resultQuery = resultQuery.ApplyThenByDesc(orderByObject.ColumnName); isFirst = false; } } else { if (isFirst) { resultQuery = resultQuery.ApplyOrderBy(orderByObject.ColumnName); } else { resultQuery = resultQuery.ApplyThenBy(orderByObject.ColumnName); isFirst = false; } } } } results = await resultQuery.ToListAsync(); } } return(new PagingResult <T>() { Data = results, TotalCount = totalCounts }); }