예제 #1
0
        /// <inheritdoc />
        public async Task <QueryResult> ApplyAndExecuteAsync(IQueryable queryable, string queryString, CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();
            var entityQuery = new EntityQuery(queryString);
            var elementType = TypeFns.GetElementType(queryable.GetType());

            entityQuery.Validate(elementType, _entityMetadataProvider);

            int?inlineCount = null;

            queryable = entityQuery.ApplyWhere(queryable, elementType);
            if (entityQuery.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)queryable);
            }

            queryable = EntityQuery.ApplyCustomLogic?.Invoke(entityQuery, queryable, elementType) ?? queryable;
            queryable = entityQuery.ApplyOrderBy(queryable, elementType);
            queryable = entityQuery.ApplySkip(queryable, elementType);
            queryable = entityQuery.ApplyTake(queryable, elementType);
            queryable = entityQuery.ApplySelect(queryable, elementType);
            queryable = ApplyExpand(queryable, entityQuery, elementType, out var postExecuteExpandPaths);
            var listResult = await(ToListAsync((dynamic)queryable, cancellationToken)).ConfigureAwait(false);

            if (postExecuteExpandPaths?.Count > 0)
            {
                _proxyInitializer.Initialize(listResult, postExecuteExpandPaths);
            }

            listResult = EntityQuery.AfterExecution?.Invoke(entityQuery, queryable, listResult) ?? listResult;

            return(new QueryResult(listResult, inlineCount));
        }
예제 #2
0
        /// <inheritdoc />
        public QueryResult ApplyAndExecute(IQueryable queryable, string queryString)
        {
            var entityQuery = new EntityQuery(queryString);
            var elementType = TypeFns.GetElementType(queryable.GetType());

            entityQuery.Validate(elementType, _entityMetadataProvider);

            int?inlineCount = null;

            queryable = entityQuery.ApplyWhere(queryable, elementType);
            if (entityQuery.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)queryable);
            }

            queryable = EntityQuery.ApplyCustomLogic?.Invoke(entityQuery, queryable, elementType) ?? queryable;
            queryable = entityQuery.ApplyOrderBy(queryable, elementType);
            queryable = entityQuery.ApplySkip(queryable, elementType);
            queryable = entityQuery.ApplyTake(queryable, elementType);
            queryable = entityQuery.ApplySelect(queryable, elementType);
            queryable = ApplyExpand(queryable, entityQuery, elementType, out var postExecuteExpandPaths);
            var listResult = ToList((dynamic)queryable);

            if (postExecuteExpandPaths?.Count > 0)
            {
                _proxyInitializer.Initialize(listResult, postExecuteExpandPaths);
            }

            listResult = EntityQuery.AfterExecution?.Invoke(entityQuery, queryable, listResult) ?? listResult;

            return(new QueryResult(listResult, inlineCount));
        }
예제 #3
0
        /// <summary>
        /// Apply the select clause to the queryable
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="selectQueryString"></param>
        /// <returns></returns>
        public virtual IQueryable ApplySelect(IQueryable queryable, string selectQueryString)
        {
            var selectClauses = selectQueryString.Split(',').Select(sc => sc.Replace('/', '.')).ToList();
            var elementType   = TypeFns.GetElementType(queryable.GetType());
            var func          = QueryBuilder.BuildSelectFunc(elementType, selectClauses);

            return(func(queryable));
        }
예제 #4
0
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            var qs = QueryFns.ExtractAndDecodeQueryString(context);

            if (qs == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var queryable = QueryFns.ExtractQueryable(context);

            if (queryable == null)
            {
                base.OnActionExecuted(context);
            }

            var eq      = new EntityQuery(qs);
            var eleType = TypeFns.GetElementType(queryable.GetType());

            eq.Validate(eleType);


            int?inlineCount = null;

            var originalQueryable = queryable;

            queryable = eq.ApplyWhere(queryable, eleType);

            if (eq.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)queryable);
            }

            queryable = eq.ApplyOrderBy(queryable, eleType);
            queryable = eq.ApplySkip(queryable, eleType);
            queryable = eq.ApplyTake(queryable, eleType);
            queryable = eq.ApplySelect(queryable, eleType);
            queryable = eq.ApplyExpand(queryable, eleType);


            if (queryable != originalQueryable)
            {
                // if a select or expand was encountered we need to
                // execute the DbQueries here, so that any exceptions thrown can be properly returned.
                // if we wait to have the query executed within the serializer, some exceptions will not
                // serialize properly.
                var listResult = Enumerable.ToList((dynamic)queryable);
                var qr         = new QueryResult(listResult, inlineCount);
                context.Result = new ObjectResult(qr);
            }


            base.OnActionExecuted(context);
        }
예제 #5
0
        private IQueryable ApplyNestedOrderBy(IQueryable queryable, ODataQueryOptions queryOptions)
        {
            var    elementType       = TypeFns.GetElementType(queryable.GetType());
            var    result            = queryable;
            string inlinecountString = queryOptions.RawValues.InlineCount;

            if (!string.IsNullOrWhiteSpace(inlinecountString))
            {
                if (inlinecountString == "allpages")
                {
                    if (result is IQueryable)
                    {
                        var inlineCount = (Int64)Queryable.Count((dynamic)result);
                        queryOptions.Request.SetInlineCount(inlineCount);
                    }
                }
            }

            var orderByClauses = queryOptions.RawValues.OrderBy.Split(',').ToList();
            var isThenBy       = false;

            orderByClauses.ForEach(obc => {
                var func = QueryBuilder.BuildOrderByFunc(isThenBy, elementType, obc);
                result   = func(result);
                isThenBy = true;
            });

            var skipQueryString = queryOptions.RawValues.Skip;

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            var topQueryString = queryOptions.RawValues.Top;

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }



            return(result);
        }
예제 #6
0
        /// <summary>
        /// Apply the select clause to the queryable
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="selectQueryString"></param>
        /// <returns></returns>
        public virtual IQueryable ApplySelect(IQueryable queryable, ODataQueryOptions queryOptions)
        {
            var selectQueryString = queryOptions.RawValues.Select;

            if (string.IsNullOrEmpty(selectQueryString))
            {
                return(queryable);
            }
            var selectClauses = selectQueryString.Split(',').Select(sc => sc.Replace('/', '.')).ToList();
            var elementType   = TypeFns.GetElementType(queryable.GetType());
            var func          = QueryBuilder.BuildSelectFunc(elementType, selectClauses);

            return(func(queryable));
        }
예제 #7
0
        public virtual IQueryable ApplyOrderBy(IQueryable queryable, ODataQueryOptions queryOptions)
        {
            var elementType = TypeFns.GetElementType(queryable.GetType());
            var result      = queryable;

            var orderByString = queryOptions.RawValues.OrderBy;

            if (!string.IsNullOrEmpty(orderByString))
            {
                var orderByClauses = orderByString.Split(',').ToList();
                var isThenBy       = false;
                orderByClauses.ForEach(obc => {
                    var parts        = obc.Trim().Replace("  ", " ").Split(' ');
                    var propertyPath = parts[0];
                    bool isDesc      = parts.Length > 1 && parts[1] == "desc";
                    var odi          = new OrderByClause.OrderByItem(parts[0], isDesc);

                    var func = QueryBuilder.BuildOrderByFunc(isThenBy, elementType, odi);
                    result   = func(result);
                    isThenBy = true;
                });
            }

            var skipQueryString = queryOptions.RawValues.Skip;

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            var topQueryString = queryOptions.RawValues.Top;

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            return(result);
        }
예제 #8
0
        public virtual IQueryable ApplyOrderBy(IQueryable queryable, ODataQueryOptions queryOptions)
        {
            var elementType = TypeFns.GetElementType(queryable.GetType());
            var result      = queryable;

            var orderByString = queryOptions.RawValues.OrderBy;

            if (!string.IsNullOrEmpty(orderByString))
            {
                // apply the new order
                var orderByClauses = orderByString.Split(',').ToList();
                var isThenBy       = false;
                orderByClauses.ForEach(obc =>
                {
                    var func = QueryBuilder.BuildOrderByFunc(isThenBy, elementType, obc);
                    result   = func(result);
                    isThenBy = true;
                });
            }

            var skipQueryString = queryOptions.RawValues.Skip;

            if (!string.IsNullOrWhiteSpace(skipQueryString))
            {
                var count  = int.Parse(skipQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Skip <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            var topQueryString = queryOptions.RawValues.Top;

            if (!string.IsNullOrWhiteSpace(topQueryString))
            {
                var count  = int.Parse(topQueryString);
                var method = TypeFns.GetMethodByExample((IQueryable <String> q) => Queryable.Take <String>(q, 999), elementType);
                var func   = BuildIQueryableFunc(elementType, method, count);
                result = func(result);
            }

            return(result);
        }
예제 #9
0
        private static MethodCallExpression GenerateMethodCall(Expression queryableExpr, string methodName, String propertyName, Type forceEntityType = null)
        {
            var              baseEntityType = TypeFns.GetElementType(queryableExpr.Type);
            var              entityType     = forceEntityType != null ? forceEntityType : baseEntityType;
            Type             selectorResultType;
            LambdaExpression selector  = GeneratePropertySelector(entityType, propertyName, out selectorResultType);
            var              parmTypes = new List <Type> {
                baseEntityType
            };

            if (forceEntityType != null)
            {
                parmTypes.Add(forceEntityType);
            }
            parmTypes.Add(selectorResultType);
            var methodMI = typeof(EntityFrameworkQueryableExtensions).GetMethods().Where(me => me.Name == methodName).FirstOrDefault();
            MethodCallExpression resultExp = Expression.Call(methodMI.DeclaringType, methodName,
                                                             parmTypes.ToArray(),
                                                             queryableExpr, Expression.Quote(selector));

            return(resultExp);
        }
예제 #10
0
        public IQueryable IncludeByString(IQueryable queryable, String expandQueryString)
        {
            var result = queryable.Expression;

            if (string.IsNullOrEmpty(expandQueryString))
            {
                return(queryable);
            }

            var baseElementType = TypeFns.GetElementType(queryable.GetType());

            expandQueryString = expandQueryString.Replace('/', '.');
            var expandEntities = expandQueryString.Split('.').ToList();
            var isThenInclude  = false;

            expandEntities.ForEach(propertyName =>
            {
                var parmElementType = isThenInclude ? GetIncludeableElementType(result.Type) : TypeFns.GetElementType(result.Type);

                var propertyInfo = parmElementType.GetProperty(propertyName);
                if (propertyInfo == null)
                {
                    throw new Exception("Unable to locate property: " + propertyName + " on type: " + parmElementType.ToString());
                }

                if (isThenInclude)
                {
                    result = ThenIncludeString(result, propertyName, parmElementType);
                }
                else
                {
                    result = IncludeString(result, propertyName);
                }


                isThenInclude = true;
            });
            return(queryable.Provider.CreateQuery(result) as IQueryable);
        }
예제 #11
0
        /// <summary>
        /// Apply to expands clause to the queryable
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="expandsQueryString"></param>
        /// <returns></returns>
        public virtual IQueryable ApplyExpand(IQueryable queryable, ODataQueryOptions queryOptions)
        {
            return(queryable);

            var queryable2        = queryable as IQueryable <object>;
            var expandQueryString = queryOptions.RawValues.Expand;

            if (string.IsNullOrEmpty(expandQueryString))
            {
                return(queryable);
            }
            var eleType = TypeFns.GetElementType(queryable2.GetType());

            expandQueryString.Split(',').Select(s => s.Trim().Replace('/', '.')).ToList().ForEach(expand => {
                //queryable = ((dynamic)queryable).Include(expand.Replace('/', '.'));
                queryable2 = queryable2.Include(expand);
                //var method = TypeFns.GetMethodByExample((IQueryable<String> q) => EntityFrameworkQueryableExtensions.Include<String>(q, "dummyPath"), eleType);
                //var func = QueryBuilder.BuildIQueryableFunc(eleType, method, expand);
                //queryable2 = func(queryable2 as IQueryable) as IQueryable<object>;
            });
            return(queryable2 as IQueryable);
        }
예제 #12
0
        /// <summary>
        /// Apply the queryOptions to the query.
        /// This method handles nested order-by statements the the current ASP.NET web api does not yet support.
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="queryOptions"></param>
        /// <param name="querySettings"></param>
        /// <returns></returns>
        public IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions, ODataQuerySettings querySettings)
        {
            // HACK: this is a hack because on a bug in querySettings.EnsureStableOrdering = true that overrides
            // any existing order by clauses, instead of appending to them.
            querySettings.EnsureStableOrdering = false;

            // Basic idea here is the current WebApi OData cannot support the following operations
            // 1) "orderby" with  nested properties
            // 2) "select" with complex types
            // 3) "selects" of "nested" properties unless accompanied by the appropriate "expand".
            //     i.e. can't do Customers.select("orders") unless we also add expand("orders")

            // The workaround here is to bypass "select" and "orderBy" processing under these conditions
            // This involves removing the "offending" queryOptions before asking the WebApi2 OData processing to do its thing
            // and then post processing the resulting IQueryable.
            // We actually do this with all selects because it's easier than trying to determine if they are actually problematic.

            // Another approach that DOESN'T work is to let WebApi2 OData try to do it stuff and then only handle the cases where it throws an exception.
            // This doesn't work because WebApi2 OData will actually just skip the portions of the query that it can't process and return what it can ( under some conditions).

            var expandQueryString  = queryOptions.RawValues.Expand;
            var orderByQueryString = queryOptions.RawValues.OrderBy;
            var selectQueryString  = queryOptions.RawValues.Select;
            var filterQueryString  = queryOptions.RawValues.Filter;

            ODataQueryOptions newQueryOptions = queryOptions;

            if (!string.IsNullOrWhiteSpace(selectQueryString))
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }
            else if ((!string.IsNullOrWhiteSpace(orderByQueryString)) && orderByQueryString.IndexOf('/') >= 0)
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }
            //else if (ManuallyExpand && !string.IsNullOrWhiteSpace(expandQueryString))
            else if (!string.IsNullOrWhiteSpace(expandQueryString))
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }
            else if (!string.IsNullOrWhiteSpace(filterQueryString))
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }


            if (newQueryOptions == queryOptions)
            {
                return(queryOptions.ApplyTo(queryable, querySettings));
            }
            else
            {
                // remove inlinecount or it will be executed two times
                if (newQueryOptions.InlineCount != null)
                {
                    newQueryOptions = QueryHelper.RemoveInlineCount(newQueryOptions);
                }

                // apply default processing first with "unsupported" stuff removed.
                var q = newQueryOptions.ApplyTo(queryable, querySettings);
                // then apply unsupported stuff.

                // remove any ordering
                q = RemoveOrderBy(q);

                // apply any filtering
                q = ApplyFilter(q, queryOptions);

                string inlinecountString = queryOptions.RawValues.InlineCount;
                if (!string.IsNullOrWhiteSpace(inlinecountString))
                {
                    if (inlinecountString == "allpages")
                    {
                        // TODO: make this asynch
                        //var inlineCount = (Int64)Queryable.LongCount((dynamic)q);
                        //queryOptions.Request.SetInlineCount(inlineCount);

                        // create new query for count
                        var countQ = q.Provider.CreateQuery(q.Expression) as IQueryable;
                        if (_LongCountAsynchMI == null)
                        {
                            _LongCountAsynchMI = typeof(EntityFrameworkQueryableExtensions).GetMethods().Where(me => me.Name == "LongCountAsync" && me.GetParameters().Count() == 2).FirstOrDefault();
                        }
                        var countQEntityType = TypeFns.GetElementType(q.Expression.Type);
                        var methodMI         = _LongCountAsynchMI.MakeGenericMethod(countQEntityType);

                        try
                        {
                            this._inlineCountT = methodMI.Invoke(countQ, new Object[] { countQ, new System.Threading.CancellationToken() }) as Task <long>;
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                }

                q = ApplyOrderBy(q, queryOptions);
                var q2 = ApplySelect(q, queryOptions);
                if (q2 == q)
                {
                    q2 = ApplyExpand(q, queryOptions);
                }

                return(q2);
            }
        }
예제 #13
0
        /// <summary>
        /// Replaces the response.Content with the query results, wrapped in a QueryResult object if necessary.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <param name="responseObject"></param>
        /// <param name="queryable"></param>
        public virtual async Task <bool> WrapResult(HttpRequestMessage request, HttpResponseMessage response, IQueryable queryResult)
        {
            //Object tmp;
            //request.Properties.TryGetValue("MS_InlineCount", out tmp);
            //var inlineCount = (Int64?)tmp;

            // if a select or expand was encountered we need to
            // execute the DbQueries here, so that any exceptions thrown can be properly returned.
            // if we wait to have the query executed within the serializer, some exceptions will not
            // serialize properly.

            dynamic listQueryResult = null;

            try
            {
                // try entity core method first
                if (_toListAsynchMI == null)
                {
                    _toListAsynchMI = typeof(EntityFrameworkQueryableExtensions).GetMethods().Where(me => me.Name == "ToListAsync" && me.GetParameters().Count() == 2).FirstOrDefault();
                }
                var countQEntityType = TypeFns.GetElementType(queryResult.Expression.Type);
                var methodMI         = _toListAsynchMI.MakeGenericMethod(countQEntityType);

                var   resultT = methodMI.Invoke(queryResult, new Object[] { queryResult, new System.Threading.CancellationToken() }) as Task;
                await resultT;
                listQueryResult = (resultT as dynamic).Result;
            }
            catch (Exception ex)
            {
                try
                {
                    // try old method on EF core failure as not every query will be an EF core query
                    listQueryResult = Enumerable.ToList((dynamic)queryResult);
                }
                catch (Exception ex2)
                {
                    throw ex2;
                }
            }

            var elementType = queryResult.ElementType;

            if (elementType.Name.StartsWith("SelectAllAndExpand"))
            {
                var prop = elementType.GetProperties().FirstOrDefault(pi => pi.Name == "Instance");
                var mi   = prop.GetGetMethod();
                var lqr  = (List <Object>)listQueryResult;
                listQueryResult = (dynamic)lqr.Select(item => {
                    var instance = mi.Invoke(item, null);
                    return((Object)instance);
                }).ToList();
            }

            // HierarchyNodeExpressionVisitor
            listQueryResult = PostExecuteQuery((IEnumerable)listQueryResult);

            if (listQueryResult != null || this._inlineCountT != null)
            {
                Object result = listQueryResult;
                if (this._inlineCountT != null)
                {
                    var inlineCount = await this._inlineCountT;
                    result = new QueryResult()
                    {
                        Results = listQueryResult, InlineCount = inlineCount
                    };
                }

                var formatter = ((dynamic)response.Content).Formatter;
                var oc        = new ObjectContent(result.GetType(), result, formatter);
                response.Content = oc;
            }
            return(true);
        }
예제 #14
0
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            var qs = QueryFns.ExtractAndDecodeQueryString(context);

            if (qs == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var queryable = QueryFns.ExtractQueryable(context);

            if (queryable == null)
            {
                base.OnActionExecuted(context);

                return;
            }

            var eq      = new EntityQuery(qs);
            var eleType = TypeFns.GetElementType(queryable.GetType());

            eq.Validate(eleType);


            int?inlineCount = null;

            queryable = eq.ApplyWhere(queryable, eleType);

            if (eq.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)queryable);
            }

            queryable = eq.ApplyOrderBy(queryable, eleType);
            queryable = eq.ApplySkip(queryable, eleType);
            queryable = eq.ApplyTake(queryable, eleType);
            queryable = eq.ApplySelect(queryable, eleType);
            queryable = eq.ApplyExpand(queryable, eleType);

            // if a select or expand was encountered we need to
            // execute the DbQueries here, so that any exceptions thrown can be properly returned.
            // if we wait to have the query executed within the serializer, some exceptions will not
            // serialize properly.
            var listResult   = Enumerable.ToList((dynamic)queryable);
            var qr           = new QueryResult(listResult, inlineCount);
            var breezeConfig = context.HttpContext.RequestServices.GetService <IBreezeConfig>();

            context.Result = new ObjectResult(qr)
            {
                Formatters = new FormatterCollection <IOutputFormatter>
                {
                    #if NETCOREAPP3_1 || NETCOREAPP3_0
                    new NewtonsoftJsonOutputFormatter(breezeConfig.GetJsonSerializerSettings(),
                                                      context.HttpContext.RequestServices.GetRequiredService <ArrayPool <char> >(),
                                                      context.HttpContext.RequestServices.GetRequiredService <MvcOptions>())
                    #else
                    new JsonOutputFormatter(breezeConfig.GetJsonSerializerSettings(),
                                            context.HttpContext.RequestServices.GetRequiredService <ArrayPool <char> >())
                    #endif
                }
            };

            var session = GetSession(queryable);
            if (session != null)
            {
                Close(session);
            }

            base.OnActionExecuted(context);
        }
예제 #15
0
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            var objResult = context.Result as ObjectResult;

            if (objResult == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var qs = context.HttpContext.Request.QueryString;
            var q  = WebUtility.UrlDecode(qs.Value);

            if (q.Length == 0)
            {
                base.OnActionExecuted(context);
                return;
            }
            q = q.Substring(1, q.Length - 2);


            var eq      = new EntityQuery(q);
            var eleType = TypeFns.GetElementType(objResult.Value.GetType());

            eq.Validate(eleType);
            // TODO: handle IEnumerable as well.
            var result      = (IQueryable)objResult.Value;
            int?inlineCount = null;

            if (eq.WherePredicate != null)
            {
                result = QueryBuilder.ApplyWhere(result, eleType, eq.WherePredicate);
            }

            if (eq.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)result);
            }

            if (eq.OrderByClause != null)
            {
                result = QueryBuilder.ApplyOrderBy(result, eleType, eq.OrderByClause);
            }

            if (eq.SkipCount.HasValue)
            {
                result = QueryBuilder.ApplySkip(result, eleType, eq.SkipCount.Value);
            }

            if (eq.TakeCount.HasValue)
            {
                result = QueryBuilder.ApplyTake(result, eleType, eq.TakeCount.Value);
            }

            if (eq.SelectClause != null)
            {
                result = QueryBuilder.ApplySelect(result, eleType, eq.SelectClause);
            }

            if (eq.ExpandClause != null)
            {
                eq.ExpandClause.PropertyPaths.ToList().ForEach(expand => {
                    result = ((dynamic)result).Include(expand.Replace('/', '.'));
                });
            }

            if (objResult.Value != result)
            {
                // if a select or expand was encountered we need to
                // execute the DbQueries here, so that any exceptions thrown can be properly returned.
                // if we wait to have the query executed within the serializer, some exceptions will not
                // serialize properly.
                var listResult = Enumerable.ToList((dynamic)result);
                var qr         = new QueryResult(listResult, inlineCount);
                context.Result = new ObjectResult(qr);
            }


            base.OnActionExecuted(context);
        }
예제 #16
0
        public override void OnActionExecuted(HttpActionExecutedContext context)
        {
            var qs = QueryFns.ExtractAndDecodeQueryString(context);

            if (qs == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var queryable = QueryFns.ExtractQueryable(context);

            if (queryable == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var eq      = new EntityQuery(qs);
            var eleType = TypeFns.GetElementType(queryable.GetType());

            eq.Validate(eleType);


            int?inlineCount = null;

            var originalQueryable = queryable;

            queryable = eq.ApplyWhere(queryable, eleType);

            IFutureValue <int> inlineCountFuture = null;

            if (eq.IsInlineCountEnabled)
            {
                if (UseFuture)
                {
                    var countExpr = GetCountExpressionMethod.MakeGenericMethod(eleType).Invoke(this, new object[0]);
                    inlineCountFuture = (IFutureValue <int>)ToFutureValueMethod.MakeGenericMethod(eleType, typeof(int))
                                        .Invoke(null, new[] { queryable, countExpr });
                }
                else
                {
                    inlineCount = (int)Queryable.Count((dynamic)queryable);
                }
            }

            queryable = eq.ApplyOrderBy(queryable, eleType);
            queryable = eq.ApplySkip(queryable, eleType);
            queryable = eq.ApplyTake(queryable, eleType);
            queryable = eq.ApplySelect(queryable, eleType);
            queryable = eq.ApplyExpand(queryable, eleType);


            if (queryable != originalQueryable)
            {
                // if a select or expand was encountered we need to
                // execute the DbQueries here, so that any exceptions thrown can be properly returned.
                // if we wait to have the query executed within the serializer, some exceptions will not
                // serialize properly.

                dynamic listResult;
                if (UseFuture)
                {
                    var future = ToFutureMethod.MakeGenericMethod(eleType).Invoke(null, new object[] { queryable });
                    listResult = Enumerable.ToList((dynamic)future.GetType().GetMethod("GetEnumerable").Invoke(future, new object[0]));
                }
                else
                {
                    listResult = Enumerable.ToList((dynamic)queryable);
                }

                var qr = new QueryResult(listResult, inlineCountFuture?.Value ?? inlineCount);

                if (CloseSession)
                {
                    var session = GetSession(queryable);
                    if (session != null)
                    {
                        Close(session);
                    }
                }

                context.Response = context.Request.CreateResponse(HttpStatusCode.OK, qr);
            }

            base.OnActionExecuted(context);
        }