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));
        }
Beispiel #3
0
        /// <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
            });
        }