コード例 #1
0
        /// <summary>
        /// Execute the query represented by an OData URI against an <c>IQueryable</c> data source
        /// </summary>
        /// <param name="query"><c>IQueryable</c> data source</param>
        /// <param name="inputType">Model data type</param>
        /// <param name="dynamicAccessor">Expression for accessing fields on dynamic model objects</param>
        public ODataQueryable <object> Execute(IQueryable query, ExecutionSettings settings = null)
        {
            if (query == null)
            {
                throw new ArgumentNullException("query", "Query cannot be null");
            }

            settings = settings ?? ExecutionSettings.Empty;
            var queryResult      = query;
            var constrainedQuery = query;
            var path             = settings.GetEdmSource(this);
            var inputType        = settings.GetInputType(query);
            var dynamicAccessor  = settings.GetDynamicAccessor();
            var lookupByKey      = false;

            var children = this.QueryOption.Where(n => !(n is IgnoredNode) && !(n is AliasNode)).ToList();

            // Try and do an ID lookup if applicable
            var segments     = PathSegments.ToArray();
            var functionNode = segments.FirstOrDefault() as CallNode;

            if (functionNode != null && segments.Length == 1)
            {
                var entity = ((IEdmCollectionType)path.Type).ElementType.ToStructuredType() as IEdmEntityType;
                if (entity != null && entity.Key().Count() == functionNode.Arguments.Count)
                {
                    var keys = entity.Key().ToArray();
                    var root = default(ODataNode);
                    for (var i = 0; i < keys.Length; i++)
                    {
                        var newNode = ODataNode.Equals(ODataNode.Identifier(keys[i].Name), functionNode.Arguments[i]);
                        if (root == null)
                        {
                            root = newNode;
                        }
                        else
                        {
                            newNode = ODataNode.And(root, newNode);
                        }
                    }

                    children.RemoveByFilter(n => n is FilterNode);
                    children.Add(ODataNode.Filter(root));
                    lookupByKey = true;
                }
            }

            var maxPageSize = settings.GetMaxPageSize();

            if (maxPageSize.HasValue && (!QueryOption.Top.HasValue || maxPageSize.Value < QueryOption.Top.Value))
            {
                children.RemoveByFilter(n => n is TopNode);
                children.Add(ODataNode.Top(ODataNode.Literal(maxPageSize.Value)));
            }
            children.Sort();

            // These should always come first
            foreach (var node in children.Where(o => !(o is SelectNode)))
            {
                BuildQuery(node, inputType, dynamicAccessor, ref queryResult, ref constrainedQuery);
            }

            var selectNode = children.FirstOrDefault(o => o is SelectNode);

            if (selectNode != null)
            {
                constrainedQuery = ProjectQuery(constrainedQuery, selectNode, inputType, dynamicAccessor);
            }

            return(new ODataQueryable <object>(constrainedQuery, this)
            {
                LookupByKey = lookupByKey
            });
        }