예제 #1
0
 private static Expression SelectResourceByKey(Expression queryExpression, ResourceType resourceType, KeyInstance key)
 {
     for (int i = 0; i < resourceType.KeyProperties.Count; i++)
     {
         Expression expression2;
         ResourceProperty property = resourceType.KeyProperties[i];
         object obj2 = key.AreValuesNamed ? key.NamedValues[property.Name] : key.PositionalValues[i];
         ParameterExpression expression = Expression.Parameter(queryExpression.ElementType(), "element");
         if (property.CanReflectOnInstanceTypeProperty)
         {
             expression2 = Expression.Property(expression, property.Name);
         }
         else
         {
             expression2 = Expression.Convert(Expression.Call(null, DataServiceProviderMethods.GetValueMethodInfo, expression, Expression.Constant(property)), property.Type);
         }
         LambdaExpression predicate = Expression.Lambda(Expression.Equal(expression2, Expression.Constant(obj2)), new ParameterExpression[] { expression });
         queryExpression = queryExpression.QueryableWhere(predicate);
     }
     return queryExpression;
 }
        /// <summary>
        /// Composes the specified <paramref name="queryExpression"/> for the 
        /// given <paramref name="container"/> with authorization
        /// callbacks.
        /// </summary>
        /// <param name="service">Data service on which to invoke method.</param>
        /// <param name="container">resource set to compose with.</param>
        /// <param name="queryExpression">Query to compose.</param>
        /// <returns>The resulting composed query.</returns>
        internal static Expression ComposeResourceContainer(IDataService service, ResourceSetWrapper container, Expression queryExpression)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(container != null, "container != null");
            Debug.Assert(queryExpression != null, "queryExpression != null");

            MethodInfo[] methods = container.QueryInterceptors;
            if (methods != null)
            {
                for (int i = 0; i < methods.Length; i++)
                {
                    Expression predicate;
                    try
                    {
                        predicate = (Expression)methods[i].Invoke(service.Instance, WebUtil.EmptyObjectArray);
                    }
                    catch (TargetInvocationException tie)
                    {
                        ErrorHandler.HandleTargetInvocationException(tie);
                        throw;
                    }

                    if (predicate == null)
                    {
                        throw new InvalidOperationException(Strings.DataService_AuthorizationReturnedNullQuery(methods[i].Name, methods[i].DeclaringType.FullName));
                    }

                    // predicate is LambdaExpression -- otherwise signature check missed something and following cast would throw
                    queryExpression = queryExpression.QueryableWhere((LambdaExpression)predicate);
                }
            }

            return queryExpression;
        }
예제 #3
0
        /// <summary>Filters a query like a SQL WHERE clause does.</summary>
        /// <param name="service">Service with data and configuration.</param>
        /// <param name="requestDescription">RequestDescription instance containing information about the current request being parsed.</param>
        /// <param name="source">Original source for query expression.</param>
        /// <returns>The composed query expression.</returns>
        internal static Expression Where(IDataService service, RequestDescription requestDescription, Expression source)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(source != null, "source != null");
            Debug.Assert(requestDescription != null, "requestDescription != null");

            FilterClause filterClause = new RequestExpressionParser(service, requestDescription).ParseFilter();

            if (filterClause == null)
            {
                return source;
            }

            bool filterQueryApplicable = requestDescription.TargetKind == RequestTargetKind.Resource
                                         || requestDescription.TargetKind == RequestTargetKind.OpenProperty
                                         || requestDescription.TargetKind == RequestTargetKind.ComplexObject
                                         || requestDescription.CountOption == RequestQueryCountOption.CountSegment;

            if (!filterQueryApplicable)
            {
                throw DataServiceException.CreateBadRequestError(Strings.RequestQueryProcessor_QueryFilterOptionNotApplicable);
            }

            Type queryElementType = source.ElementType();
            Debug.Assert(queryElementType != null, "queryElementType != null");

            ParameterExpression parameterForIt = Expression.Parameter(queryElementType, "it");
            Debug.Assert(
                (requestDescription.TargetResourceSet == null && (requestDescription.TargetResourceType == null || requestDescription.TargetResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)) ||
                (requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.ResourceTypeKind == ResourceTypeKind.EntityType),
                "setForIt cannot be null if typeForIt is an entity type.");
            Debug.Assert(
                requestDescription.TargetResourceType == null && parameterForIt.Type == typeof(object) ||
                requestDescription.TargetResourceType != null && requestDescription.TargetResourceType.InstanceType == parameterForIt.Type,
                "non-open type expressions should have a typeForIt");

            var translator = NodeToExpressionTranslator.Create(service, requestDescription, parameterForIt);
            LambdaExpression lambda = translator.TranslateFilterClause(filterClause);
            return source.QueryableWhere(lambda);
        }
예제 #4
0
 internal static Expression ComposeResourceContainer(IDataService service, ResourceSetWrapper container, Expression queryExpression)
 {
     MethodInfo[] queryInterceptors = container.QueryInterceptors;
     if (queryInterceptors != null)
     {
         for (int i = 0; i < queryInterceptors.Length; i++)
         {
             Expression expression;
             try
             {
                 expression = (Expression) queryInterceptors[i].Invoke(service.Instance, WebUtil.EmptyObjectArray);
             }
             catch (TargetInvocationException exception)
             {
                 ErrorHandler.HandleTargetInvocationException(exception);
                 throw;
             }
             if (expression == null)
             {
                 throw new InvalidOperationException(System.Data.Services.Strings.DataService_AuthorizationReturnedNullQuery(queryInterceptors[i].Name, queryInterceptors[i].DeclaringType.FullName));
             }
             queryExpression = queryExpression.QueryableWhere((LambdaExpression) expression);
         }
     }
     return queryExpression;
 }
예제 #5
0
        /// <summary>Selects a single resource by key values.</summary>
        /// <param name="queryExpression">Base query for resources</param>
        /// <param name="resourceType">resource type whose keys are specified</param>
        /// <param name="key">Key values for the given resource type.</param>
        /// <returns>A new query that selects the single resource that matches the specified key values.</returns>
        private static Expression SelectResourceByKey(Expression queryExpression, ResourceType resourceType, KeySegment key)
        {
            Debug.Assert(queryExpression != null, "queryExpression != null");
            Debug.Assert(key != null, "key != null");
            
            List<KeyValuePair<string, object>> keyValues = key.Keys.ToList();
            Debug.Assert(keyValues.Count != 0, "keyValues.Count != 0");
            Debug.Assert(resourceType.KeyProperties.Count == keyValues.Count, "resourceType.KeyProperties.Count == keyValues.Count");

            for (int i = 0; i < resourceType.KeyProperties.Count; i++)
            {
                ResourceProperty keyProperty = resourceType.KeyProperties[i];
                Debug.Assert(keyProperty.IsOfKind(ResourcePropertyKind.Key), "keyProperty.IsOfKind(ResourcePropertyKind.Key)");

                object keyValue;
                if (keyValues.Count == 0)
                {
                    keyValue = keyValues[0].Value;
                }
                else
                {
                    keyValue = keyValues.Single(v => v.Key == keyProperty.Name).Value;    
                }
                
                var binaryValue = keyValue as byte[];
                if (binaryValue != null && keyProperty.Type == typeof(System.Data.Linq.Binary))
                {
                    keyValue = new System.Data.Linq.Binary(binaryValue);
                }

                var stringValue = keyValue as string;
                if (stringValue != null && keyProperty.Type == typeof(XElement))
                {
                    keyValue = XElement.Parse(stringValue);
                }

                if (keyProperty.Type == typeof(DateTime))
                {
                    Debug.Assert(keyValue != null && keyValue is DateTimeOffset, "For DateTime properties, the value must be read as DateTimeOffset");
                    keyValue = WebUtil.ConvertDateTimeOffsetToDateTime((DateTimeOffset)keyValue);
                }

                ParameterExpression parameter = Expression.Parameter(queryExpression.ElementType(), "element");
                Expression e;
                if (keyProperty.CanReflectOnInstanceTypeProperty)
                {
                    e = Expression.Property(parameter, keyProperty.Name);
                }
                else
                {
                    e = Expression.Call(null /*instance*/, DataServiceProviderMethods.GetValueMethodInfo, parameter, Expression.Constant(keyProperty));
                    e = Expression.Convert(e, keyProperty.Type);
                }

                BinaryExpression body = Expression.Equal(e, Expression.Constant(keyValue));
                LambdaExpression predicate = Expression.Lambda(body, parameter);
                queryExpression = queryExpression.QueryableWhere(predicate);
            }

            return queryExpression;
        }