private Expression AddOrderByQueryForSource(Expression source, OrderByClause orderbyClause, Type elementType) { if (orderbyClause != null) { LambdaExpression orderByExpression = FilterBinder.Bind(orderbyClause, elementType, _model, _settings, _assembliesResolver); source = ExpressionHelpers.OrderBy(source, orderByExpression, elementType, orderbyClause.Direction); } return(source); }
internal static LambdaExpression Bind(IQueryable baseQuery, OrderByClause orderBy, Type elementType, ODataQueryContext context, ODataQuerySettings querySettings) { Contract.Assert(orderBy != null); Contract.Assert(elementType != null); Contract.Assert(context != null); FilterBinder binder = context.GetFilterBinder(querySettings); binder._filterType = elementType; binder.BaseQuery = baseQuery; return(BindOrderByClause(binder, orderBy, elementType)); }
internal static Expression Bind(IQueryable baseQuery, FilterClause filterClause, Type filterType, ODataQueryContext context, ODataQuerySettings querySettings) { Contract.Assert(filterClause != null); Contract.Assert(filterType != null); Contract.Assert(context != null); FilterBinder binder = context.GetFilterBinder(querySettings); binder._filterType = filterType; binder.BaseQuery = baseQuery; return(BindFilterClause(binder, filterClause, filterType)); }
internal static LambdaExpression BindFilterClause(FilterBinder binder, FilterClause filterClause, Type filterType) { LambdaExpression filter = binder.BindExpression(filterClause.Expression, filterClause.RangeVariable, filterType); filter = Expression.Lambda(binder.ApplyNullPropagationForFilterBody(filter.Body), filter.Parameters); Type expectedFilterType = typeof(Func <,>).MakeGenericType(filterType, typeof(bool)); if (filter.Type != expectedFilterType) { throw Error.Argument("filterType", SRResources.CannotCastFilter, filter.Type.FullName, expectedFilterType.FullName); } return(filter); }
private static FilterBinder GetOrCreateFilterBinder(ODataQueryContext context, ODataQuerySettings querySettings) { FilterBinder binder = null; if (context.RequestContainer != null) { binder = context.RequestContainer.GetRequiredService <FilterBinder>(); if (binder != null && binder.Model != context.Model && binder.Model == EdmCoreModel.Instance) { binder.Model = context.Model; } } return(binder ?? new FilterBinder(querySettings, AssemblyResolverHelper.Default, context.Model)); }
internal static Expression Bind(FilterClause filterClause, Type filterType, IEdmModel model, IAssemblyResolver assembliesResolver, ODataQuerySettings querySettings) { if (filterClause == null) { throw Error.ArgumentNull("filterClause"); } if (filterType == null) { throw Error.ArgumentNull("filterType"); } if (model == null) { throw Error.ArgumentNull("model"); } if (assembliesResolver == null) { throw Error.ArgumentNull("assembliesResolver"); } FilterBinder binder = new FilterBinder(model, assembliesResolver, querySettings, filterType); return(BindFilterClause(binder, filterClause, filterType)); }
internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property, Expression source, FilterClause filterClause) { Contract.Assert(elementType != null); Contract.Assert(property != null); Contract.Assert(source != null); IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType; Contract.Assert(declaringType != null, "only entity types are projected."); // derived property using cast if (elementType != declaringType) { Type castType = EdmLibHelpers.GetClrType(declaringType, _model); if (castType == null) { throw new ODataException("TODO: " /*Error.Format(SRResources.MappingDoesNotContainResourceType, * declaringType.FullName())*/); } source = Expression.TypeAs(source, castType); } string propertyName = EdmLibHelpers.GetClrPropertyName(property, _model); Expression propertyValue = Expression.Property(source, propertyName); Type nullablePropertyType = propertyValue.Type.ToNullable(); Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue); if (filterClause != null && property.Type.IsCollection()) { IEdmTypeReference edmElementType = property.Type.AsCollection().ElementType(); Type clrElementType = EdmLibHelpers.GetClrType(edmElementType, _model); if (clrElementType == null) { throw new ODataException("TODO:" /*Error.Format(SRResources.MappingDoesNotContainResourceType, * edmElementType.FullName())*/); } Expression filterSource = typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType) ? Expression.Call( ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType), nullablePropertyValue) : nullablePropertyValue; Expression filterPredicate = FilterBinder.Bind(filterClause, clrElementType, /*_context.RequestContainer*/ null); MethodCallExpression filterResult = Expression.Call( ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType), filterSource, filterPredicate); nullablePropertyType = filterResult.Type; if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // nullablePropertyValue == null ? null : filterResult nullablePropertyValue = Expression.Condition( test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: nullablePropertyType), ifFalse: filterResult); } else { nullablePropertyValue = filterResult; } } if (!property.Type.IsCollection()) { if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : propertyValue propertyValue = Expression.Condition( test: Expression.Equal(source, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: nullablePropertyType), ifFalse: nullablePropertyValue); } else { // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null. propertyValue = nullablePropertyValue; } } return(propertyValue); }
internal static LambdaExpression BindOrderByClause(FilterBinder binder, OrderByClause orderBy, Type elementType) { LambdaExpression orderByLambda = binder.BindExpression(orderBy.Expression, orderBy.RangeVariable, elementType); return(orderByLambda); }
internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property, Expression source, FilterClause filterClause) { Contract.Assert(elementType != null); Contract.Assert(property != null); Contract.Assert(source != null); IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType; Contract.Assert(declaringType != null, "only entity types are projected."); // derived property using cast if (elementType != declaringType) { Type castType = EdmLibHelpers.GetClrType(declaringType, _model); if (castType == null) { throw new ODataException("TODO: " /*Error.Format(SRResources.MappingDoesNotContainResourceType, * declaringType.FullName())*/); } source = Expression.TypeAs(source, castType); } string propertyName = EdmLibHelpers.GetClrPropertyName(property, _model); Expression propertyValue = Expression.Property(source, propertyName); Type nullablePropertyType = propertyValue.Type.ToNullable(); Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue); Type clrElementType = EdmLibHelpers.GetClrType(elementType, _model); Expression filterSource = null; var interceptorContainer = new InterceptorContainer(clrElementType, _serviceProvider); if ((filterClause != null || interceptorContainer.Any) && property.Type.IsCollection()) { if (clrElementType == null) { throw new ODataException("TODO:" /*Error.Format(SRResources.MappingDoesNotContainResourceType, * edmElementType.FullName())*/); } filterSource = typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType) ? Expression.Call( ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType), nullablePropertyValue) : nullablePropertyValue; Expression filterPredicate = FilterBinder.Bind(filterClause, clrElementType, _serviceProvider); MethodCallExpression filterResult = Expression.Call( ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType), filterSource, filterPredicate); nullablePropertyType = filterResult.Type; if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // nullablePropertyValue == null ? null : filterResult nullablePropertyValue = Expression.Condition( test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: nullablePropertyType), ifFalse: filterResult); } else { nullablePropertyValue = filterResult; } } if ((filterClause != null || interceptorContainer.Any) && property.Type.IsCollection()) { filterSource = typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType) ? Expression.Call( ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType), nullablePropertyValue) : nullablePropertyValue; } // TODO: Fix possibly ambiguity resolution if the // implementation class has multiple methods names // "Intercept" var handleNull = false; source = ApplyInterceptors(source, clrElementType, _serviceProvider); //interceptorContainer.ForEach(source, (src, predicate) => //{ // if (filterSource != null) // { // // We have a collection to intercept // ApplyFilterToQuery( // clrElementType, // filterSource, // predicate, // ref nullablePropertyType, // ref nullablePropertyValue); // } // else // { // handleNull = true; // // Apply our predicate locally // nullablePropertyValue = Expression.Condition( // test: Expression.Invoke(predicate, nullablePropertyValue), // ifTrue: propertyValue, // ifFalse: Expression.Constant(value: null, type: nullablePropertyType) // ); // //ApplyFilterToQuery( // // clrElementType, // // propertyValue, // // predicate, // // ref nullablePropertyType, // // ref nullablePropertyValue); // } //}); if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : propertyValue propertyValue = Expression.Condition( test: Expression.Equal(source, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: nullablePropertyType), ifFalse: nullablePropertyValue); } else { // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null. propertyValue = nullablePropertyValue; } return(propertyValue); }