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; }
/// <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); }
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; }
/// <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; }