/// <summary>
        /// Creates a new instance.
        /// </summary>
        internal static IMapper <TOptions, TValue> Create(Expression <Func <TOptions, TValue> > expression)
        {
            var action = ExpressionHelpers.CreatePropertyWriter(expression, out var propertyName);

            return(new PropertyMapper <TOptions, TValue>(action, propertyName));
        }
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (!IsParentParameterExpression())
            {
                return(base.VisitMethodCall(node));
            }

            if (!object.ReferenceEquals(CurrentParameter, node.GetParameterExpression()))
            {
                return(base.VisitMethodCall(node));
            }

            if (node.Method.IsStatic)
            {
                if (!IsExtentionMethod())
                {
                    return(base.VisitMethodCall(node));
                }

                if (node.Method.IsGenericMethod)
                {
                    return(Expression.Call
                           (
                               node.Method.DeclaringType,
                               node.Method.Name,
                               node.Method.GetGenericArguments(),
                               GetNewArgumentsForExtensionMethod()
                           ));
                }
                else
                {
                    return(Expression.Call(node.Method, GetNewArgumentsForExtensionMethod()));
                }
            }

            //instance method
            if (node.Method.IsGenericMethod)
            {
                return(Expression.Call
                       (
                           GetNewParent(),
                           node.Method.Name,
                           node.Method.GetGenericArguments(),
                           node.Arguments.ToArray()
                       ));
            }
            else
            {
                return(Expression.Call
                       (
                           GetNewParent(),
                           node.Method,
                           node.Arguments
                       ));
            }

            Expression[] GetNewArgumentsForExtensionMethod()
            {
                Expression[] arguments = node.Arguments.ToArray();
                arguments[0] = GetNewParent();
                return(arguments.ToArray());
            }

            Expression GetNewParent()
            => string.IsNullOrEmpty(ParentFullName)
                ? NewParameter
                : ExpressionHelpers.MemberAccesses(ParentFullName, NewParameter);

            bool IsParentParameterExpression()
            {
                if (node.Method.IsStatic)
                {
                    return(node.Arguments[0] is ParameterExpression);
                }

                if (!node.Method.IsStatic)
                {
                    return(node.Object is ParameterExpression);
                }

                return(false);
            }

            bool IsExtentionMethod()
            => node.Method.IsDefined(typeof(ExtensionAttribute), true);
        }
 private IQueryable ApplyToCore(IQueryable query)
 {
     return(ExpressionHelpers.Skip(query, Value, Context.EntityClrType));
 }
Exemple #4
0
        private IOrderedQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings)
        {
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            ICollection <OrderByNode> nodes = OrderByNodes;

            bool       alreadyOrdered = false;
            IQueryable querySoFar     = query;

            HashSet <object> propertiesSoFar     = new HashSet <object>();
            HashSet <string> openPropertiesSoFar = new HashSet <string>();
            bool             orderByItSeen       = false;

            foreach (OrderByNode node in nodes)
            {
                OrderByPropertyNode     propertyNode     = node as OrderByPropertyNode;
                OrderByOpenPropertyNode openPropertyNode = node as OrderByOpenPropertyNode;
                OrderByCountNode        countNode        = node as OrderByCountNode;

                if (propertyNode != null)
                {
                    // Use autonomy class to achieve value equality for HasSet.
                    var edmPropertyWithPath    = new { propertyNode.Property, propertyNode.PropertyPath };
                    OrderByDirection direction = propertyNode.Direction;

                    // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows
                    if (propertiesSoFar.Contains(edmPropertyWithPath))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, edmPropertyWithPath.PropertyPath));
                    }

                    propertiesSoFar.Add(edmPropertyWithPath);

                    if (propertyNode.OrderByClause != null)
                    {
                        querySoFar = AddOrderByQueryForProperty(query, querySettings, propertyNode.OrderByClause, querySoFar, direction, alreadyOrdered);
                    }
                    else
                    {
                        querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, edmPropertyWithPath.Property, direction, Context.ElementClrType, alreadyOrdered);
                    }

                    alreadyOrdered = true;
                }
                else if (openPropertyNode != null)
                {
                    // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows
                    if (openPropertiesSoFar.Contains(openPropertyNode.PropertyName))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, openPropertyNode.PropertyPath));
                    }

                    openPropertiesSoFar.Add(openPropertyNode.PropertyName);
                    Contract.Assert(openPropertyNode.OrderByClause != null);
                    querySoFar     = AddOrderByQueryForProperty(query, querySettings, openPropertyNode.OrderByClause, querySoFar, openPropertyNode.Direction, alreadyOrdered);
                    alreadyOrdered = true;
                }
                else if (countNode != null)
                {
                    Contract.Assert(countNode.OrderByClause != null);
                    querySoFar     = AddOrderByQueryForProperty(query, querySettings, countNode.OrderByClause, querySoFar, countNode.Direction, alreadyOrdered);
                    alreadyOrdered = true;
                }
                else
                {
                    // This check prevents queries with duplicate nodes (e.g. $orderby=$it,$it,$it,$it...) from causing stack overflows
                    if (orderByItSeen)
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateIt));
                    }

                    querySoFar     = ExpressionHelpers.OrderByIt(querySoFar, node.Direction, Context.ElementClrType, alreadyOrdered);
                    alreadyOrdered = true;
                    orderByItSeen  = true;
                }
            }

            return(querySoFar as IOrderedQueryable);
        }
Exemple #5
0
        private Expression BuildPropertyContainer(IEdmEntityType elementType, Expression source,
                                                  Dictionary <IEdmNavigationProperty, ExpandedNavigationSelectItem> propertiesToExpand,
                                                  ISet <IEdmStructuralProperty> propertiesToInclude, ISet <IEdmStructuralProperty> autoSelectedProperties, bool isSelectingOpenTypeSegments)
        {
            IList <NamedPropertyExpression> includedProperties = new List <NamedPropertyExpression>();

            foreach (KeyValuePair <IEdmNavigationProperty, ExpandedNavigationSelectItem> kvp in propertiesToExpand)
            {
                IEdmNavigationProperty       propertyToExpand = kvp.Key;
                ExpandedNavigationSelectItem expandItem       = kvp.Value;
                SelectExpandClause           projection       = expandItem.SelectAndExpand;

                Expression propertyName  = CreatePropertyNameExpression(elementType, propertyToExpand, source);
                Expression propertyValue = CreatePropertyValueExpressionWithFilter(elementType, propertyToExpand, source,
                                                                                   expandItem.FilterOption);
                Expression nullCheck = GetNullCheckExpression(propertyToExpand, propertyValue, projection);

                Expression countExpression = CreateTotalCountExpression(propertyValue, expandItem);

                // projection can be null if the expanded navigation property is not further projected or expanded.
                if (projection != null)
                {
                    propertyValue = ProjectAsWrapper(propertyValue, projection, propertyToExpand.ToEntityType(), expandItem.NavigationSource as IEdmEntitySet, expandItem);
                }

                NamedPropertyExpression propertyExpression = new NamedPropertyExpression(propertyName, propertyValue);
                if (projection != null)
                {
                    if (!propertyToExpand.Type.IsCollection())
                    {
                        propertyExpression.NullCheck = nullCheck;
                    }
                    else if (_settings.PageSize != null)
                    {
                        propertyExpression.PageSize = _settings.PageSize.Value;
                    }

                    propertyExpression.TotalCount  = countExpression;
                    propertyExpression.CountOption = expandItem.CountOption;
                }

                includedProperties.Add(propertyExpression);
            }

            foreach (IEdmStructuralProperty propertyToInclude in propertiesToInclude)
            {
                Expression propertyName  = CreatePropertyNameExpression(elementType, propertyToInclude, source);
                Expression propertyValue = CreatePropertyValueExpression(elementType, propertyToInclude, source);
                includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue));
            }

            foreach (IEdmStructuralProperty propertyToInclude in autoSelectedProperties)
            {
                Expression propertyName  = CreatePropertyNameExpression(elementType, propertyToInclude, source);
                Expression propertyValue = CreatePropertyValueExpression(elementType, propertyToInclude, source);
                includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue)
                {
                    AutoSelected = true
                });
            }

            if (isSelectingOpenTypeSegments)
            {
                var dynamicPropertyDictionary = EdmLibHelpers.GetDynamicPropertyDictionary(elementType, _model);

                Expression propertyName          = Expression.Constant(dynamicPropertyDictionary.Name);
                Expression propertyValue         = Expression.Property(source, dynamicPropertyDictionary.Name);
                Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);
                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: propertyValue.Type.ToNullable()),
                        ifFalse: nullablePropertyValue);
                }
                else
                {
                    propertyValue = nullablePropertyValue;
                }

                includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue));
            }

            // create a property container that holds all these property names and values.
            return(PropertyContainer.CreatePropertyContainer(includedProperties));
        }
Exemple #6
0
        public static IHtmlContent GenerateHtml <TModel, TProperty>(IHtmlHelper <TModel> htmlHelper,
                                                                    Expression <Func <TModel, TProperty> > propertyLambdaExpression,
                                                                    FieldsetViewModel fieldsetOptions = null,
                                                                    HintViewModel hintOptions         = null,
                                                                    Dictionary <TProperty, LabelViewModel> itemLabelOptions           = null,
                                                                    Dictionary <TProperty, HintViewModel> itemHintOptions             = null,
                                                                    Dictionary <TProperty, Func <object, object> > conditionalOptions = null,
                                                                    string classes = null)
            where TModel : GovUkViewModel
        {
            PropertyInfo property = ExpressionHelpers.GetPropertyFromExpression(propertyLambdaExpression);

            ThrowIfPropertyTypeIsNotNullableEnum(property);
            string propertyName = property.Name;

            TModel    model = htmlHelper.ViewData.Model;
            TProperty currentlySelectedValue =
                ExpressionHelpers.GetPropertyValueFromModelAndExpression(model, propertyLambdaExpression);

            Type  enumType      = Nullable.GetUnderlyingType(typeof(TProperty));
            Array allEnumValues = Enum.GetValues(enumType);


            List <ItemViewModel> radios = allEnumValues
                                          .OfType <object>()
                                          .Select(enumValue =>
            {
                bool isEnumValueCurrentlySelected = enumValue.ToString() == currentlySelectedValue.ToString();
                string radioLabelText             = GetRadioLabelText(enumType, enumValue);

                var radioItemViewModel = new RadioItemViewModel
                {
                    Value   = enumValue.ToString(),
                    Id      = $"GovUk_Radio_{propertyName}_{enumValue}",
                    Checked = isEnumValueCurrentlySelected,
                    Label   = new LabelViewModel()
                };

                if (conditionalOptions != null && conditionalOptions.TryGetValue((TProperty)enumValue, out Func <object, object> conditionalHtml))
                {
                    radioItemViewModel.Conditional = new Conditional {
                        Html = conditionalHtml
                    };
                }

                if (itemLabelOptions != null && itemLabelOptions.TryGetValue((TProperty)enumValue, out LabelViewModel labelViewModel))
                {
                    radioItemViewModel.Label = labelViewModel;
                }
                if (radioItemViewModel.Label.Text == null && radioItemViewModel.Label.Html == null)
                {
                    radioItemViewModel.Label.Text = radioLabelText;
                }

                if (itemHintOptions != null && itemHintOptions.TryGetValue((TProperty)enumValue, out HintViewModel hintViewModel))
                {
                    radioItemViewModel.Hint = hintViewModel;
                }

                return(radioItemViewModel);
            })
                                          .Cast <ItemViewModel>()
                                          .ToList();

            var radiosViewModel = new RadiosViewModel
            {
                Name     = $"GovUk_Radio_{propertyName}",
                IdPrefix = $"GovUk_{propertyName}",
                Items    = radios,
                Fieldset = fieldsetOptions,
                Hint     = hintOptions,
                Classes  = classes
            };

            if (model.HasErrorFor(property))
            {
                radiosViewModel.ErrorMessage = new ErrorMessageViewModel
                {
                    Text = model.GetErrorFor(property)
                };
            }

            return(htmlHelper.Partial("/GovUkDesignSystemComponents/Radios.cshtml", radiosViewModel));
        }
 public void ExpressionChecker_NoException(int memberValue)
 {
     Assert.DoesNotThrow(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Volume, memberValue));
 }
        protected override Expression VisitMember(MemberExpression node)
        {
            string sourcePath;

            var parameterExpression = node.GetParameterExpression();

            if (parameterExpression == null)
            {
                return(base.VisitMember(node));
            }

            InfoDictionary.Add(parameterExpression, TypeMappings);

            var sType = parameterExpression.Type;

            if (InfoDictionary.ContainsKey(parameterExpression) && node.IsMemberExpression())
            {
                sourcePath = node.GetPropertyFullName();
            }
            else
            {
                return(base.VisitMember(node));
            }

            var propertyMapInfoList = new List <PropertyMapInfo>();

            FindDestinationFullName(sType, InfoDictionary[parameterExpression].DestType, sourcePath, propertyMapInfoList);
            string fullName;

            if (propertyMapInfoList.Any(x => x.CustomExpression != null))
            {
                var last = propertyMapInfoList.Last(x => x.CustomExpression != null);
                var beforeCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) =>
                {
                    if (propertyMapInfoList.IndexOf(next) < propertyMapInfoList.IndexOf(last))
                    {
                        list.Add(next);
                    }
                    return(list);
                });

                var afterCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) =>
                {
                    if (propertyMapInfoList.IndexOf(next) > propertyMapInfoList.IndexOf(last))
                    {
                        list.Add(next);
                    }
                    return(list);
                });

                fullName = BuildFullName(beforeCustExpression);
                var visitor = new PrependParentNameVisitor(last.CustomExpression.Parameters[0].Type /*Parent type of current property*/, fullName, InfoDictionary[parameterExpression].NewParameter);

                var ex = propertyMapInfoList[propertyMapInfoList.Count - 1] != last
                    ? visitor.Visit(last.CustomExpression.Body.MemberAccesses(afterCustExpression))
                    : visitor.Visit(last.CustomExpression.Body);

                this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, ex.Type);
                return(ex);
            }
            fullName = BuildFullName(propertyMapInfoList);
            var me = ExpressionHelpers.MemberAccesses(fullName, InfoDictionary[parameterExpression].NewParameter);

            this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, me.Type);
            return(me);
        }
Exemple #9
0
        private IOrderedQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings)
        {
            if (Context.ElementClrType == null)
            {
                throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo");
            }

            ICollection <OrderByNode> nodes = OrderByNodes;

            bool       alreadyOrdered = false;
            IQueryable querySoFar     = query;

            HashSet <IEdmProperty> propertiesSoFar = new HashSet <IEdmProperty>();
            bool orderByItSeen = false;

            foreach (OrderByNode node in nodes)
            {
                OrderByPropertyNode propertyNode = node as OrderByPropertyNode;

                if (propertyNode != null)
                {
                    IEdmProperty     property  = propertyNode.Property;
                    OrderByDirection direction = propertyNode.Direction;

                    // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows
                    if (propertiesSoFar.Contains(property))
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, property.Name));
                    }
                    propertiesSoFar.Add(property);

                    if (propertyNode.OrderByClause != null)
                    {
                        // Ensure we have decided how to handle null propagation
                        ODataQuerySettings updatedSettings = querySettings;
                        if (querySettings.HandleNullPropagation == HandleNullPropagationOption.Default)
                        {
                            updatedSettings = new ODataQuerySettings(updatedSettings);
                            updatedSettings.HandleNullPropagation = HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(query);
                        }

                        LambdaExpression orderByExpression =
                            FilterBinder.Bind(propertyNode.OrderByClause, Context.ElementClrType, Context.Model, updatedSettings);
                        querySoFar = ExpressionHelpers.OrderBy(querySoFar, orderByExpression, direction, Context.ElementClrType, alreadyOrdered);
                    }
                    else
                    {
                        querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, property, direction, Context.ElementClrType, alreadyOrdered);
                    }
                    alreadyOrdered = true;
                }
                else
                {
                    // This check prevents queries with duplicate nodes (e.g. $orderby=$it,$it,$it,$it...) from causing stack overflows
                    if (orderByItSeen)
                    {
                        throw new ODataException(Error.Format(SRResources.OrderByDuplicateIt));
                    }

                    querySoFar     = ExpressionHelpers.OrderByIt(querySoFar, node.Direction, Context.ElementClrType, alreadyOrdered);
                    alreadyOrdered = true;
                    orderByItSeen  = true;
                }
            }

            return(querySoFar as IOrderedQueryable);
        }
 public void ExpressionChecker_NoException(string memberValue)
 {
     Assert.DoesNotThrow(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Symbol, memberValue));
 }
Exemple #11
0
        public static IIndex <TDatabase, TTable> Index <TDatabase, TTable>(this IIndexBuilder <TDatabase, TTable> @this,
                                                                           Expression <Func <IOrderFilter <TTable>, object> > keyColumns,
                                                                           bool unique    = false,
                                                                           string name    = null,
                                                                           bool clustered = false,
                                                                           Expression <Func <TTable, object> > includedColumns = null)
        {
            var builder = @this as InternalTableBuilder <TDatabase, TTable>;

            var indexKeyColumns      = ExpressionHelpers.ParseOrderedMultiPropertySelector(keyColumns ?? throw ModelBuilderError.ArgumentNull(nameof(keyColumns)).AsException()).MatchColumns(builder.Name, builder.Columns);
            var indexIncludedColumns = includedColumns == null?ImmutableArray.Create <ColumnModel>() : ExpressionHelpers.ParseMultiPropertySelector(includedColumns).MatchColumns(builder.Name, builder.Columns);

            var indexName = name ?? BuilderHelper.GenerateKeyName("IX", builder.Schema, builder.Name, indexKeyColumns.Select(c => c.Name));

            if (clustered)
            {
                var priorClustered = builder.PrimaryKey?.IsClustered == true ? builder.PrimaryKey.Name
                                                                             : builder.Indexes.FirstOrDefault(i => i.IsClustered)?.Name;
                if (priorClustered != null)
                {
                    throw ModelBuilderError.IndexClusteredAlreadySpecified(priorClustered).AsException();
                }
            }

            {
                var column = indexIncludedColumns.FirstOrDefault(i => indexKeyColumns.Any(k => k.Property.Name == i.Property.Name));
                if (column != null)
                {
                    throw ModelBuilderError.IndexIncludedColumnAlreadyInKeyColumns(column.Name).AsException();
                }
            }

            builder.Indexes.Add(new IndexModel(name: indexName,
                                               keyColumns: indexKeyColumns.ToImmutableArray(),
                                               isUnique: unique,
                                               isClustered: clustered,
                                               includedColumns: indexIncludedColumns.ToImmutableArray()));

            return(builder);
        }
Exemple #12
0
        public static Task <JobMetadataResult[]> SearchCriteria(JobSearchCriteria criteria)
        {
            var manager = new SQLiteJobQueueManager(new SQLiteJobQueueDataConnectionFactory(TempDevInfo.ConnString),
                                                    TempDevInfo.TableConfigurations["console"], new NullOnMissingTypeJobTypeResolver());
            Expression <Func <SqlCommonDbOddJobMetaData, bool> > expr = null;

            if (!string.IsNullOrWhiteSpace(criteria.QueueName))
            {
                expr = ExpressionHelpers.CombineBinaryExpression(expr,
                                                                 (a) => a.QueueName.ToLower().Contains(criteria.QueueName.ToLower()), false);
            }

            if (!string.IsNullOrWhiteSpace(criteria.MethodName) && criteria.UseMethod)
            {
                expr = ExpressionHelpers.CombineBinaryExpression(expr,
                                                                 (a) => a.MethodName.ToLower().Contains(criteria.MethodName.ToLower()), false);
            }
            if (!string.IsNullOrWhiteSpace(criteria.Status) && criteria.UseStatus)
            {
                expr = ExpressionHelpers.CombineBinaryExpression(expr,
                                                                 (a) => a.Status.ToLower().Contains(criteria.Status.ToLower()), false);
            }

            /*       if (statusCriteria != null && statusCriteria.Any())
             *     {
             *         expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.Status.LikeAnyLower(statusCriteria),
             *             requireAll);
             *
             *     }
             *
             *     if (jobNameCriteria != null && jobNameCriteria.Any())
             *     {
             *         expr = ExpressionHelpers.CombineBinaryExpression(expr,
             *             (a) => a.MethodName.LikeAnyUpper(jobNameCriteria), requireAll);
             *     }
             *
             *     if (jobGuids != null && jobGuids.Any())
             *     {
             *         expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.JobGuid.In(jobGuids), requireAll);
             *     }
             *
             *     expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => (
             *         (createdNoLaterThan == null || a.CreatedDate <= createdNoLaterThan)
             *         &&
             *         (createdNoEarlierThan == null || a.CreatedDate >= createdNoEarlierThan)
             *     ), requireAll);
             *     expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => (
             *         (lastExecutedNoLaterThan == null || a.LastAttempt <= lastExecutedNoLaterThan)
             *         &&
             *         (lastExecutedNoEarlierThan == null || a.LastAttempt >= lastExecutedNoEarlierThan)
             *     ), requireAll);
             */
            var result = expr == null ? new JobMetadataResult[] {} : manager.GetSerializableJobsByCriteria(expr).Select(q => new JobMetadataResult()
            {
                ExecutionTime = q.ExecutionTime.ToString(),
                JobArgs       = q.JobArgs.Select(r => new JobParameterDto()
                {
                    Ordinal = r.Ordinal, Name = r.Name, Type = r.TypeName, Value = r.Value
                }).ToArray(),
                JobId = q.JobId,
                MethodGenericTypes = q.MethodGenericTypes.ToArray(),
                MethodName         = q.MethodName, Queue = q.QueueName,
                RetryParameters    = new JobRetryParameters()
                {
                    LastAttempt = q.RetryParameters.LastAttempt, RetryCount = q.RetryParameters.RetryCount,
                    MaxRetries  = q.RetryParameters.MaxRetries, MinRetryWait = q.RetryParameters.MinRetryWait
                },

                Status = q.Status, TypeExecutedOn = q.TypeExecutedOn
            });

            return(Task.FromResult(result.ToArray()));
        }
 protected MemberExpression GetMemberExpressionFromMemberMaps(string fullName, Expression visitedParentExpr)
 => ExpressionHelpers.MemberAccesses(fullName, visitedParentExpr);
        /// <summary>
        /// Asynchronously executes the query flow.
        /// </summary>
        /// <param name="context">
        /// The query context.
        /// </param>
        /// <param name="cancellationToken">
        /// A cancellation token.
        /// </param>
        /// <returns>
        /// A task that represents the asynchronous
        /// operation whose result is a query result.
        /// </returns>
        public static async Task <QueryResult> QueryAsync(
            QueryContext context,
            CancellationToken cancellationToken)
        {
            Ensure.NotNull(context, "context");

            // process query expression
            var expression = context.Request.Expression;
            var visitor    = new QueryExpressionVisitor(context);

            expression = visitor.Visit(expression);

            // get element type
            Type elementType = null;
            var  queryType   = expression.Type.FindGenericType(typeof(IQueryable <>));

            if (queryType != null)
            {
                elementType = queryType.GetGenericArguments()[0];
            }

            // append count expression if requested
            if (elementType != null && context.Request.ShouldReturnCount)
            {
                expression  = ExpressionHelpers.Count(expression, elementType);
                elementType = null; // now return type is single int
            }

            // execute query
            QueryResult result;
            var         executor = context.GetHookHandler <IQueryExecutor>();

            if (executor == null)
            {
                throw new NotSupportedException(Resources.QueryExecutorMissing);
            }

            if (elementType != null)
            {
                var query  = visitor.BaseQuery.Provider.CreateQuery(expression);
                var method = typeof(IQueryExecutor)
                             .GetMethod("ExecuteQueryAsync")
                             .MakeGenericMethod(elementType);
                var parameters = new object[]
                {
                    context, query, cancellationToken
                };
                var task = method.Invoke(executor, parameters) as Task <QueryResult>;
                result = await task;
            }
            else
            {
                var method = typeof(IQueryExecutor)
                             .GetMethod("ExecuteSingleAsync")
                             .MakeGenericMethod(expression.Type);
                var parameters = new object[]
                {
                    context, visitor.BaseQuery, expression, cancellationToken
                };
                var task = method.Invoke(executor, parameters) as Task <QueryResult>;
                result = await task;
            }

            if (result != null)
            {
                result.ResultsSource = visitor.EntitySet;
            }

            return(result);
        }
 public void ExpressionChecker_NoException(decimal memberValue)
 {
     Assert.DoesNotThrow(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Open, memberValue));
 }
Exemple #16
0
        public void OnMatch(List <Expression> contentExpressions, PropertyInfo propertyInfo, ParameterExpression paramT,
                            ParameterExpression paramWriter)
        {
            var propType      = propertyInfo.PropertyType;
            var elemType      = propType.GetElementType();
            var typeLenAttr   = propertyInfo.GetCustomAttribute <LengthTypeAttribute>();
            var customVarAttr = propertyInfo.GetCustomAttribute <CustomVarAttribute>();

            var typeLen            = typeLenAttr == null ? typeof(short) : typeLenAttr.TypeLen;
            var isTypeLenCustom    = typeLenAttr != null && typeLenAttr.IsCustomVar;
            var isContentCustom    = customVarAttr != null;
            var isContentPrimitive = PrimitiveTypes.Primitives.Contains(elemType);

            var miLen = isTypeLenCustom ?
                        typeof(IWriter).GetMethod("WriteCustom").MakeGenericMethod(typeLen)
              : typeof(IWriter).GetMethod("WriteValue").MakeGenericMethod(typeLen);

            var paramProp = Expression.Property(paramT, propertyInfo);
            var paramLen  = ExpressionHelpers.GetLengthProperty(paramT, propertyInfo);
            var i         = Expression.Variable(typeof(int), "i");

            var callMiLen = Expression.Call(paramWriter, miLen, Expression.Convert(paramLen, typeLen));

            contentExpressions.Add(callMiLen);

            Expression finalExpression;

            if (!isContentPrimitive)
            {
                var dlg = typeof(Serializer <>).MakeGenericType(elemType).GetProperty("SerializeAction");

                var content = Expression.Invoke(Expression.Property(null, dlg), Expression.ArrayAccess(paramProp, i), paramWriter);

                finalExpression = ExpressionHelpers.For(i,
                                                        Expression.Constant(0),
                                                        Expression.LessThan(i, paramLen),
                                                        Expression.PostIncrementAssign(i),
                                                        content);
            }
            else
            {
                if (!isContentCustom)
                {
                    if (elemType == typeof(byte) || elemType == typeof(sbyte))
                    {
                        var mi = typeof(IWriter).GetMethod("WriteArray").MakeGenericMethod(elemType);

                        finalExpression = Expression.Call(paramWriter, mi, paramProp, paramLen);
                    }
                    else
                    {
                        var mi = typeof(IWriter).GetMethod("WriteValue").MakeGenericMethod(elemType);

                        var content = Expression.Call(paramWriter, mi,
                                                      Expression.ArrayAccess(paramProp, i));

                        finalExpression = ExpressionHelpers.For(i,
                                                                Expression.Constant(0),
                                                                Expression.LessThan(i, paramLen),
                                                                Expression.PostIncrementAssign(i),
                                                                content);
                    }
                }
                else
                {
                    var mi = typeof(IWriter).GetMethod("WriteCustom").MakeGenericMethod(elemType);

                    var content = Expression.Call(paramWriter, mi,
                                                  Expression.ArrayAccess(paramProp, i));

                    finalExpression = ExpressionHelpers.For(i,
                                                            Expression.Constant(0),
                                                            Expression.LessThan(i, paramLen),
                                                            Expression.PostIncrementAssign(i),
                                                            content);
                }
            }

            contentExpressions.Add(finalExpression);
        }
 public void ExpressionChecker_Exception(string memberValue)
 {
     Assert.Throws <ArgumentException>(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Open, memberValue));
 }
Exemple #18
0
        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(Error.Format(SRResources.MappingDoesNotContainEntityType,
                                                          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(Error.Format(SRResources.MappingDoesNotContainEntityType,
                                                          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,
                    _model,
                    _assembliesResolver,
                    _settings);
                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 (_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);
        }
Exemple #19
0
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (ExpressionHelpers.IsQueryMethod(node))
            {
                Logger.Log($"Processing method 'Queryable.{node.Method.Name}'", Indentation.Two);

                switch (node.Method.Name)
                {
                case nameof(Queryable.Any):
                    return(Call(node, new AnyLinqExpression(node, init)));

                case nameof(Queryable.Count):
                    return(Call(node, new CountLinqExpression(node, init)));

                case nameof(Queryable.First):
                case nameof(Queryable.FirstOrDefault):
                    return(Call(node, new FirstLinqExpression(node, init)));

                case nameof(Queryable.Last):
                case nameof(Queryable.LastOrDefault):
                    if (strict)
                    {
                        throw Error.UnsupportedOptionalPredicate(node);
                    }

                    return(Call(node, new LastLinqExpression(node, init)));

                case nameof(Queryable.OrderBy):
                case nameof(Queryable.OrderByDescending):
                    return(Call(node, new OrderByLinqExpression(node, GetSortDirection(node.Method), init)));

                case nameof(Queryable.Select):
                    return(Call(node, new SelectLinqExpression(node, init)));

                case nameof(Queryable.SelectMany):
                    return(Call(node, new SelectManyLinqExpression(node, init)));

                case nameof(Queryable.Skip):
                    return(Call(node, new SkipLinqExpression(node, init)));

                case nameof(Queryable.Take):
                    return(Call(node, new TakeLinqExpression(node, init)));

                case nameof(Queryable.Where):
                    return(Call(node, new WhereLinqExpression(node, init)));

                default:

                    Logger.Log($"Encountered unsupported method {node.Method.Name}");

                    if (strict)
                    {
                        throw Error.UnsupportedLinqExpression(node.Method.Name);
                    }

                    var result = base.VisitMethodCall(node);
                    manager.Call(node.Method.Name, null);
                    return(result);
                }
            }

            return(base.VisitMethodCall(node));
        }
Exemple #20
0
        // new CollectionWrapper<ElementType> { Instance = source.Select((ElementType element) => new Wrapper { }) }
        private Expression ProjectCollection(Expression source, Type elementType, SelectExpandClause selectExpandClause, IEdmEntityType entityType, IEdmEntitySet entitySet, ExpandedNavigationSelectItem expandedItem)
        {
            ParameterExpression element = Expression.Parameter(elementType);

            // expression
            //      new Wrapper { }
            Expression projection = ProjectElement(element, selectExpandClause, entityType, entitySet);

            // expression
            //      (ElementType element) => new Wrapper { }
            LambdaExpression selector = Expression.Lambda(projection, element);

            if (expandedItem != null)
            {
                source = AddOrderByQueryForSource(source, expandedItem.OrderByOption, elementType);
            }

            if (_settings.PageSize.HasValue ||
                (expandedItem != null && (expandedItem.TopOption.HasValue || expandedItem.SkipOption.HasValue)))
            {
                // nested paging. Need to apply order by first, and take one more than page size as we need to know
                // whether the collection was truncated or not while generating next page links.
                IEnumerable <IEdmStructuralProperty> properties =
                    entityType.Key().Any()
                        ? entityType.Key()
                        : entityType
                    .StructuralProperties()
                    .Where(property => property.Type.IsPrimitive()).OrderBy(property => property.Name);

                if (expandedItem == null || expandedItem.OrderByOption == null)
                {
                    bool alreadyOrdered = false;
                    foreach (var prop in properties)
                    {
                        source = ExpressionHelpers.OrderByPropertyExpression(source, prop.Name, elementType,
                                                                             alreadyOrdered);
                        if (!alreadyOrdered)
                        {
                            alreadyOrdered = true;
                        }
                    }
                }

                if (expandedItem != null && expandedItem.SkipOption.HasValue)
                {
                    Contract.Assert(expandedItem.SkipOption.Value <= Int32.MaxValue);
                    source = ExpressionHelpers.Skip(source, (int)expandedItem.SkipOption.Value, elementType,
                                                    _settings.EnableConstantParameterization);
                }

                if (expandedItem != null && expandedItem.TopOption.HasValue)
                {
                    Contract.Assert(expandedItem.TopOption.Value <= Int32.MaxValue);
                    source = ExpressionHelpers.Take(source, (int)expandedItem.TopOption.Value, elementType,
                                                    _settings.EnableConstantParameterization);
                }

                if (_settings.PageSize.HasValue)
                {
                    source = ExpressionHelpers.Take(source, _settings.PageSize.Value + 1, elementType,
                                                    _settings.EnableConstantParameterization);
                }
            }

            // expression
            //      source.Select((ElementType element) => new Wrapper { })
            Expression selectedExpresion = Expression.Call(GetSelectMethod(elementType, projection.Type), source, selector);

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : projectedCollection
                return(Expression.Condition(
                           test: Expression.Equal(source, Expression.Constant(null)),
                           ifTrue: Expression.Constant(null, selectedExpresion.Type),
                           ifFalse: selectedExpresion));
            }
            else
            {
                return(selectedExpresion);
            }
        }
Exemple #21
0
        private LanguageExpression InlineVariables(LanguageExpression original)
        {
            var inlined = InlineVariablesRecursive(original);

            return(ExpressionHelpers.FlattenStringOperations(inlined));
        }
        public void ToNullable_Returns_SameExpressionIfTypeIsAlreadyNullable()
        {
            Expression expression = Expression.Constant("nullable string");

            Assert.Same(expression, ExpressionHelpers.ToNullable(expression));
        }
Exemple #23
0
        /// <summary>
        /// Pre flattens properties referenced in aggregate clause to avoid generation of nested queries by EF.
        /// For query like groupby((A), aggregate(B/C with max as Alias1, B/D with max as Alias2)) we need to generate
        /// .Select(
        ///     $it => new FlattenninWrapper () {
        ///         Source = $it, // Will used in groupby stage
        ///         Container = new {
        ///             Value = $it.B.C
        ///             Next = new {
        ///                 Value = $it.B.D
        ///             }
        ///         }
        ///     }
        /// )
        /// Also we need to populate expressions to access B/C and B/D in aggregate stage. It will look like:
        /// B/C : $it.Container.Value
        /// B/D : $it.Container.Next.Value
        /// </summary>
        /// <param name="query"></param>
        /// <returns>Query with Select that flattens properties</returns>
        private IQueryable FlattenReferencedProperties(IQueryable query)
        {
            if (_aggregateExpressions != null &&
                _aggregateExpressions.Any(e => e.Method != AggregationMethod.VirtualPropertyCount) &&
                _groupingProperties != null &&
                _groupingProperties.Any() &&
                (FlattenedPropertyContainer == null || !FlattenedPropertyContainer.Any())
                )
            {
                var wrapperType             = typeof(FlatteningWrapper <>).MakeGenericType(this._elementType);
                var sourceProperty          = wrapperType.GetProperty("Source");
                List <MemberAssignment> wta = new List <MemberAssignment>();
                wta.Add(Expression.Bind(sourceProperty, this._lambdaParameter));

                var aggrregatedPropertiesToFlatten = _aggregateExpressions.Where(e => e.Method != AggregationMethod.VirtualPropertyCount).ToList();
                // Generated Select will be stack like, meaning that first property in the list will be deepest one
                // For example if we add $it.B.C, $it.B.D, select will look like
                // new {
                //      Value = $it.B.C
                //      Next = new {
                //          Value = $it.B.D
                //      }
                // }
                // We are generated references (in currentContainerExpression) from  the begining of the  Select ($it.Value, then $it.Next.Value etc.)
                // We have proper match we need insert properties in reverse order
                // After this
                // properties = { $it.B.D, $it.B.C}
                // _preFlattendMAp = { {$it.B.C, $it.Value}, {$it.B.D, $it.Next.Value} }
                var properties = new NamedPropertyExpression[aggrregatedPropertiesToFlatten.Count];
                var aliasIdx   = aggrregatedPropertiesToFlatten.Count - 1;
                var aggParam   = Expression.Parameter(wrapperType, "$it");
                var currentContainerExpression = Expression.Property(aggParam, GroupByContainerProperty);
                foreach (var aggExpression in aggrregatedPropertiesToFlatten)
                {
                    var alias = "Property" + aliasIdx; // We just need unique alias, we aren't going to use it

                    // Add Value = $it.B.C
                    var propAccessExpression = BindAccessor(aggExpression.Expression);
                    var type = propAccessExpression.Type;
                    propAccessExpression = WrapConvert(propAccessExpression);
                    properties[aliasIdx] = new NamedPropertyExpression(Expression.Constant(alias), propAccessExpression);

                    // Save $it.Container.Next.Value for future use
                    UnaryExpression flatAccessExpression = Expression.Convert(
                        Expression.Property(currentContainerExpression, "Value"),
                        type);
                    currentContainerExpression = Expression.Property(currentContainerExpression, "Next");
                    _preFlattenedMap.Add(aggExpression.Expression, flatAccessExpression);
                    aliasIdx--;
                }

                var wrapperProperty = ResultClrType.GetProperty(GroupByContainerProperty);

                wta.Add(Expression.Bind(wrapperProperty, AggregationPropertyContainer.CreateNextNamedPropertyContainer(properties)));

                var flatLambda = Expression.Lambda(Expression.MemberInit(Expression.New(wrapperType), wta), _lambdaParameter);

                query = ExpressionHelpers.Select(query, flatLambda, this._elementType);

                // We applied flattening let .GroupBy know about it.
                this._lambdaParameter = aggParam;
                this._elementType     = wrapperType;
            }

            return(query);
        }