Exemple #1
0
 public bool ProbeAssemblies(params Assembly[] assembliesToProbe)
 {
     lock (_structuralTypes) {
         var assemblies = assembliesToProbe.Except(_probedAssemblies).ToList();
         if (assemblies.Any())
         {
             assemblies.ForEach(asm => {
                 _probedAssemblies.Add(asm);
                 _typeDiscoveryActions.Where(tpl => tpl.Item3 == null || tpl.Item3(asm))
                 .ForEach(tpl => {
                     var type   = tpl.Item1;
                     var action = tpl.Item2;
                     TypeFns.GetTypesImplementing(type, asm).ForEach(t => action(t));
                 });
             });
             return(true);
         }
         else
         {
             return(false);
         }
     }
 }
Exemple #2
0
        private static DataProperty CreateDataProperty(StructuralType structuralType, PropertyInfo pInfo)
        {
            var propType = pInfo.PropertyType;
            var dp       = new DataProperty(pInfo.Name);

            // TODO: handle isScalar
            if (typeof(IComplexObject).IsAssignableFrom(propType))
            {
                dp.ComplexType = GetComplexType(propType);
                dp.IsNullable  = false;
                // complex Objects do not have defaultValues currently
            }
            else
            {
                dp.ClrType      = propType;
                dp.DataType     = DataType.FromClrType(TypeFns.GetNonNullableType(propType));
                dp.IsNullable   = TypeFns.IsNullableType(propType);
                dp.DefaultValue = dp.IsNullable ? null : dp.DataType.DefaultValue;
            }

            structuralType.AddDataProperty(dp);
            return(dp);
        }
        public override void Validate(Type entityType)
        {
            if (Expr1Source == null)
            {
                throw new Exception("Unable to validate 1st expression: " + this.Expr1Source);
            }

            this._block1 = BaseBlock.CreateLHSBlock(Expr1Source, entityType);

            if (_op == Operator.In && !(Expr2Source is IList))
            {
                throw new Exception("The 'in' operator requires that its right hand argument be an array");
            }

            // Special purpose Enum handling

            var enumType = GetEnumType(this._block1);

            if (enumType != null)
            {
                if (Expr2Source != null)
                {
                    var et        = TypeFns.GetNonNullableType(enumType);
                    var expr2Enum = Enum.Parse(et, (String)Expr2Source);
                    this._block2 = BaseBlock.CreateRHSBlock(expr2Enum, entityType, null);
                }
                else
                {
                    this._block2 = BaseBlock.CreateRHSBlock(null, entityType, null);
                }
            }
            else
            {
                this._block2 = BaseBlock.CreateRHSBlock(Expr2Source, entityType, this._block1.DataType);
            }
        }
Exemple #4
0
        /// <summary>
        /// Apply the queryOptions to the query.
        /// This method handles nested order-by statements the the current ASP.NET web api does not yet support.
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="queryOptions"></param>
        /// <param name="querySettings"></param>
        /// <returns></returns>
        public IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions, ODataQuerySettings querySettings)
        {
            // HACK: this is a hack because on a bug in querySettings.EnsureStableOrdering = true that overrides
            // any existing order by clauses, instead of appending to them.
            querySettings.EnsureStableOrdering = false;

            // Basic idea here is the current WebApi OData cannot support the following operations
            // 1) "orderby" with  nested properties
            // 2) "select" with complex types
            // 3) "selects" of "nested" properties unless accompanied by the appropriate "expand".
            //     i.e. can't do Customers.select("orders") unless we also add expand("orders")

            // The workaround here is to bypass "select" and "orderBy" processing under these conditions
            // This involves removing the "offending" queryOptions before asking the WebApi2 OData processing to do its thing
            // and then post processing the resulting IQueryable.
            // We actually do this with all selects because it's easier than trying to determine if they are actually problematic.

            // Another approach that DOESN'T work is to let WebApi2 OData try to do it stuff and then only handle the cases where it throws an exception.
            // This doesn't work because WebApi2 OData will actually just skip the portions of the query that it can't process and return what it can ( under some conditions).

            var expandQueryString  = queryOptions.RawValues.Expand;
            var orderByQueryString = queryOptions.RawValues.OrderBy;
            var selectQueryString  = queryOptions.RawValues.Select;
            var filterQueryString  = queryOptions.RawValues.Filter;

            ODataQueryOptions newQueryOptions = queryOptions;

            if (!string.IsNullOrWhiteSpace(selectQueryString))
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }
            else if ((!string.IsNullOrWhiteSpace(orderByQueryString)) && orderByQueryString.IndexOf('/') >= 0)
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }
            //else if (ManuallyExpand && !string.IsNullOrWhiteSpace(expandQueryString))
            else if (!string.IsNullOrWhiteSpace(expandQueryString))
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }
            else if (!string.IsNullOrWhiteSpace(filterQueryString))
            {
                newQueryOptions = QueryHelper.RemoveSelectExpandOrderBy(newQueryOptions);
            }


            if (newQueryOptions == queryOptions)
            {
                return(queryOptions.ApplyTo(queryable, querySettings));
            }
            else
            {
                // remove inlinecount or it will be executed two times
                if (newQueryOptions.InlineCount != null)
                {
                    newQueryOptions = QueryHelper.RemoveInlineCount(newQueryOptions);
                }

                // apply default processing first with "unsupported" stuff removed.
                var q = newQueryOptions.ApplyTo(queryable, querySettings);
                // then apply unsupported stuff.

                // remove any ordering
                q = RemoveOrderBy(q);

                // apply any filtering
                q = ApplyFilter(q, queryOptions);

                string inlinecountString = queryOptions.RawValues.InlineCount;
                if (!string.IsNullOrWhiteSpace(inlinecountString))
                {
                    if (inlinecountString == "allpages")
                    {
                        // TODO: make this asynch
                        //var inlineCount = (Int64)Queryable.LongCount((dynamic)q);
                        //queryOptions.Request.SetInlineCount(inlineCount);

                        // create new query for count
                        var countQ = q.Provider.CreateQuery(q.Expression) as IQueryable;
                        if (_LongCountAsynchMI == null)
                        {
                            _LongCountAsynchMI = typeof(EntityFrameworkQueryableExtensions).GetMethods().Where(me => me.Name == "LongCountAsync" && me.GetParameters().Count() == 2).FirstOrDefault();
                        }
                        var countQEntityType = TypeFns.GetElementType(q.Expression.Type);
                        var methodMI         = _LongCountAsynchMI.MakeGenericMethod(countQEntityType);

                        try
                        {
                            this._inlineCountT = methodMI.Invoke(countQ, new Object[] { countQ, new System.Threading.CancellationToken() }) as Task <long>;
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                }

                q = ApplyOrderBy(q, queryOptions);
                var q2 = ApplySelect(q, queryOptions);
                if (q2 == q)
                {
                    q2 = ApplyExpand(q, queryOptions);
                }

                return(q2);
            }
        }
Exemple #5
0
        /// <summary>
        /// Replaces the response.Content with the query results, wrapped in a QueryResult object if necessary.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <param name="responseObject"></param>
        /// <param name="queryable"></param>
        public virtual async Task <bool> WrapResult(HttpRequestMessage request, HttpResponseMessage response, IQueryable queryResult)
        {
            //Object tmp;
            //request.Properties.TryGetValue("MS_InlineCount", out tmp);
            //var inlineCount = (Int64?)tmp;

            // if a select or expand was encountered we need to
            // execute the DbQueries here, so that any exceptions thrown can be properly returned.
            // if we wait to have the query executed within the serializer, some exceptions will not
            // serialize properly.

            dynamic listQueryResult = null;

            try
            {
                // try entity core method first
                if (_toListAsynchMI == null)
                {
                    _toListAsynchMI = typeof(EntityFrameworkQueryableExtensions).GetMethods().Where(me => me.Name == "ToListAsync" && me.GetParameters().Count() == 2).FirstOrDefault();
                }
                var countQEntityType = TypeFns.GetElementType(queryResult.Expression.Type);
                var methodMI         = _toListAsynchMI.MakeGenericMethod(countQEntityType);

                var   resultT = methodMI.Invoke(queryResult, new Object[] { queryResult, new System.Threading.CancellationToken() }) as Task;
                await resultT;
                listQueryResult = (resultT as dynamic).Result;
            }
            catch (Exception ex)
            {
                try
                {
                    // try old method on EF core failure as not every query will be an EF core query
                    listQueryResult = Enumerable.ToList((dynamic)queryResult);
                }
                catch (Exception ex2)
                {
                    throw ex2;
                }
            }

            var elementType = queryResult.ElementType;

            if (elementType.Name.StartsWith("SelectAllAndExpand"))
            {
                var prop = elementType.GetProperties().FirstOrDefault(pi => pi.Name == "Instance");
                var mi   = prop.GetGetMethod();
                var lqr  = (List <Object>)listQueryResult;
                listQueryResult = (dynamic)lqr.Select(item => {
                    var instance = mi.Invoke(item, null);
                    return((Object)instance);
                }).ToList();
            }

            // HierarchyNodeExpressionVisitor
            listQueryResult = PostExecuteQuery((IEnumerable)listQueryResult);

            if (listQueryResult != null || this._inlineCountT != null)
            {
                Object result = listQueryResult;
                if (this._inlineCountT != null)
                {
                    var inlineCount = await this._inlineCountT;
                    result = new QueryResult()
                    {
                        Results = listQueryResult, InlineCount = inlineCount
                    };
                }

                var formatter = ((dynamic)response.Content).Formatter;
                var oc        = new ObjectContent(result.GetType(), result, formatter);
                response.Content = oc;
            }
            return(true);
        }
Exemple #6
0
        public IQueryable IncludeByString(IQueryable queryable, String expandQueryString)
        {
            var result = queryable.Expression;

            if (string.IsNullOrEmpty(expandQueryString))
            {
                return(queryable);
            }

            var baseElementType = TypeFns.GetElementType(queryable.GetType());

            expandQueryString = expandQueryString.Replace('/', '.');
            var expandEntities = expandQueryString.Split('.').ToList();
            var isThenInclude  = false;

            expandEntities.ForEach(propertyName =>
            {
                var parmElementType = isThenInclude ? GetIncludeableElementType(result.Type) : TypeFns.GetElementType(result.Type);

                var propertyInfo = parmElementType.GetProperty(propertyName);
                if (propertyInfo == null)
                {
                    throw new Exception("Unable to locate property: " + propertyName + " on type: " + parmElementType.ToString());
                }

                if (isThenInclude)
                {
                    result = ThenIncludeString(result, propertyName, parmElementType);
                }
                else
                {
                    result = IncludeString(result, propertyName);
                }


                isThenInclude = true;
            });
            return(queryable.Provider.CreateQuery(result) as IQueryable);
        }
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            var qs = QueryFns.ExtractAndDecodeQueryString(context);

            if (qs == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var queryable = QueryFns.ExtractQueryable(context);

            if (queryable == null)
            {
                base.OnActionExecuted(context);

                return;
            }

            var eq      = new EntityQuery(qs);
            var eleType = TypeFns.GetElementType(queryable.GetType());

            eq.Validate(eleType);


            int?inlineCount = null;

            queryable = eq.ApplyWhere(queryable, eleType);

            if (eq.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)queryable);
            }

            queryable = eq.ApplyOrderBy(queryable, eleType);
            queryable = eq.ApplySkip(queryable, eleType);
            queryable = eq.ApplyTake(queryable, eleType);
            queryable = eq.ApplySelect(queryable, eleType);
            queryable = eq.ApplyExpand(queryable, eleType);

            // if a select or expand was encountered we need to
            // execute the DbQueries here, so that any exceptions thrown can be properly returned.
            // if we wait to have the query executed within the serializer, some exceptions will not
            // serialize properly.
            var listResult   = Enumerable.ToList((dynamic)queryable);
            var qr           = new QueryResult(listResult, inlineCount);
            var breezeConfig = context.HttpContext.RequestServices.GetService <IBreezeConfig>();

            context.Result = new ObjectResult(qr)
            {
                Formatters = new FormatterCollection <IOutputFormatter>
                {
                    #if NETCOREAPP3_1 || NETCOREAPP3_0
                    new NewtonsoftJsonOutputFormatter(breezeConfig.GetJsonSerializerSettings(),
                                                      context.HttpContext.RequestServices.GetRequiredService <ArrayPool <char> >(),
                                                      context.HttpContext.RequestServices.GetRequiredService <MvcOptions>())
                    #else
                    new JsonOutputFormatter(breezeConfig.GetJsonSerializerSettings(),
                                            context.HttpContext.RequestServices.GetRequiredService <ArrayPool <char> >())
                    #endif
                }
            };

            var session = GetSession(queryable);
            if (session != null)
            {
                Close(session);
            }

            base.OnActionExecuted(context);
        }
Exemple #8
0
        public static DataType FromType(Type type)
        {
            var nnType = TypeFns.GetNonNullableType(type);

            return(_typeMap[nnType]);
        }
        private void ParseObject(JsonContext jsonContext, EntityAspect targetAspect)
        {
            // backingStore will be null if not allowed to overwrite the entity.
            var backingStore   = (targetAspect == null) ? null : targetAspect.BackingStore;
            var dict           = (IDictionary <String, JToken>)jsonContext.JObject;
            var structuralType = jsonContext.StructuralType;

            dict.ForEach(kvp => {
                var key  = kvp.Key;
                var prop = structuralType.GetProperty(key);
                if (prop != null)
                {
                    if (prop.IsDataProperty)
                    {
                        if (backingStore != null)
                        {
                            var dp = (DataProperty)prop;
                            if (dp.IsComplexProperty)
                            {
                                var newCo     = (IComplexObject)kvp.Value.ToObject(dp.ClrType);
                                var co        = (IComplexObject)backingStore[key];
                                var coBacking = co.ComplexAspect.BackingStore;
                                newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
                                    coBacking[kvp2.Key] = kvp2.Value;
                                });
                            }
                            else
                            {
                                backingStore[key] = kvp.Value.ToObject(dp.ClrType);
                            }
                        }
                    }
                    else
                    {
                        // prop is a ComplexObject
                        var np = (NavigationProperty)prop;

                        if (kvp.Value.HasValues)
                        {
                            JsonContext newContext;
                            if (np.IsScalar)
                            {
                                var nestedOb = (JObject)kvp.Value;
                                newContext   = new JsonContext()
                                {
                                    JObject = nestedOb, ObjectType = prop.ClrType, Serializer = jsonContext.Serializer
                                };
                                var entity = (IEntity)CreateAndPopulate(newContext);
                                if (backingStore != null)
                                {
                                    backingStore[key] = entity;
                                }
                            }
                            else
                            {
                                var nestedArray = (JArray)kvp.Value;
                                var navSet      = (INavigationSet)TypeFns.CreateGenericInstance(typeof(NavigationSet <>), prop.ClrType);

                                nestedArray.Cast <JObject>().ForEach(jo => {
                                    newContext = new JsonContext()
                                    {
                                        JObject = jo, ObjectType = prop.ClrType, Serializer = jsonContext.Serializer
                                    };
                                    var entity = (IEntity)CreateAndPopulate(newContext);
                                    navSet.Add(entity);
                                });
                                // add to existing nav set if there is one otherwise just set it.
                                object tmp;
                                if (backingStore.TryGetValue(key, out tmp))
                                {
                                    var backingNavSet = (INavigationSet)tmp;
                                    navSet.Cast <IEntity>().ForEach(e => backingNavSet.Add(e));
                                }
                                else
                                {
                                    navSet.NavigationProperty = np;
                                    navSet.ParentEntity       = targetAspect.Entity;
                                    backingStore[key]         = navSet;
                                }
                            }
                        }
                        else
                        {
                            // do nothing
                            //if (!np.IsScalar) {
                            //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
                            //} else {
                            //  return null;
                            //}
                        }
                    }
                }
                else
                {
                    if (backingStore != null)
                    {
                        backingStore[key] = kvp.Value.ToObject <Object>();
                    }
                }
            });
        }
        private Expression BuildBinaryExpr(Expression expr1, Expression expr2, Operator op)
        {
            if (expr1.Type != expr2.Type)
            {
                if (TypeFns.IsNullableType(expr1.Type) && !TypeFns.IsNullableType(expr2.Type))
                {
                    expr2 = Expression.Convert(expr2, expr1.Type);
                }
                else if (TypeFns.IsNullableType(expr2.Type) && !TypeFns.IsNullableType(expr1.Type))
                {
                    expr1 = Expression.Convert(expr1, expr2.Type);
                }

                if (HasNullValue(expr2) && CannotBeNull(expr1))
                {
                    expr1 = Expression.Convert(expr1, TypeFns.GetNullableType(expr1.Type));
                }
                else if (HasNullValue(expr1) && CannotBeNull(expr2))
                {
                    expr2 = Expression.Convert(expr2, TypeFns.GetNullableType(expr2.Type));
                }
            }

            if (op == BinaryOperator.Equals)
            {
                return(Expression.Equal(expr1, expr2));
            }
            else if (op == BinaryOperator.NotEquals)
            {
                return(Expression.NotEqual(expr1, expr2));
            }
            else if (op == BinaryOperator.GreaterThan)
            {
                return(Expression.GreaterThan(expr1, expr2));
            }
            else if (op == BinaryOperator.GreaterThanOrEqual)
            {
                return(Expression.GreaterThanOrEqual(expr1, expr2));
            }
            else if (op == BinaryOperator.LessThan)
            {
                return(Expression.LessThan(expr1, expr2));
            }
            else if (op == BinaryOperator.LessThanOrEqual)
            {
                return(Expression.LessThanOrEqual(expr1, expr2));
            }
            else if (op == BinaryOperator.StartsWith)
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.StartsWith("abc"));
                return(Expression.Call(expr1, mi, expr2));
            }
            else if (op == BinaryOperator.EndsWith)
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.EndsWith("abc"));
                return(Expression.Call(expr1, mi, expr2));
            }
            else if (op == BinaryOperator.Contains)
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.Contains("abc"));
                return(Expression.Call(expr1, mi, expr2));
            }
            else if (op == BinaryOperator.In)
            {
                // TODO: need to generalize this past just 'string'
                var mi = TypeFns.GetMethodByExample((List <String> list) => list.Contains("abc"), expr1.Type);
                return(Expression.Call(expr2, mi, expr1));
            }

            return(null);
        }
        private bool CannotBeNull(Expression expr)
        {
            var t = expr.Type;

            return(TypeFns.IsPredefinedType(t) && t != typeof(String));
        }
Exemple #12
0
        // will return either a PropBlock or a LitBlock
        public static BaseBlock CreateRHSBlock(object exprSource,
                                               Type entityType, DataType otherExprDataType)
        {
            if (exprSource == null)
            {
                return(new LitBlock(exprSource, otherExprDataType));
            }

            if (exprSource is string)
            {
                var source = (string)exprSource;
                if (entityType == null)
                {
                    // if entityType is unknown then assume that the rhs is a
                    // literal
                    return(new LitBlock(source, otherExprDataType));
                }

                if (PropertySignature.IsProperty(entityType, source))
                {
                    return(new PropBlock(source, entityType));
                }
                else
                {
                    return(new LitBlock(source, otherExprDataType));
                }
            }

            if (TypeFns.IsPredefinedType(exprSource.GetType()))
            {
                return(new LitBlock(exprSource, otherExprDataType));
            }

            if (exprSource is IDictionary <string, object> )
            {
                var exprMap = (IDictionary <string, object>)exprSource;
                // note that this is NOT the same a using get and checking for null
                // because null is a valid 'value'.
                if (!exprMap.ContainsKey("value"))
                {
                    throw new Exception(
                              "Unable to locate a 'value' property on: "
                              + exprMap.ToString());
                }
                var value = exprMap["value"];

                if (exprMap.ContainsKey("isProperty"))
                {
                    return(new PropBlock((string)value, entityType));
                }
                else
                {
                    var dt       = (string)exprMap["dataType"];
                    var dataType = (dt != null) ? DataType.FromName(dt) : otherExprDataType;
                    return(new LitBlock(value, dataType));
                }
            }

            if (exprSource is IList)
            {
                // right now this pretty much implies the values on an 'in' clause
                return(new LitBlock(exprSource, otherExprDataType));
            }

            if (TypeFns.IsEnumType(exprSource.GetType()))
            {
                return(new LitBlock(exprSource, otherExprDataType));
            }

            throw new Exception(
                      "Unable to parse the right hand side of this BinaryExpression: "
                      + exprSource.ToString());
        }
Exemple #13
0
        public override Expression ToExpression(Expression inExpr)
        {
            var exprs = _exprs.Select(e => e.ToExpression(inExpr)).ToList();
            var expr  = exprs[0];

            // TODO: add the rest ...
            if (FnName == "toupper")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.ToUpper());
                return(Expression.Call(expr, mi));
            }
            else if (FnName == "tolower")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.ToLower());
                return(Expression.Call(expr, mi));
            }
            else if (FnName == "trim")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.Trim());
                return(Expression.Call(expr, mi));
            }
            else if (FnName == "length")
            {
                return(GetPropertyExpression(expr, "Length", typeof(int)));
            }
            else if (FnName == "indexof")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.IndexOf("xxx"));
                return(Expression.Call(exprs[0], mi, exprs[1]));
            }
            else if (FnName == "concat")
            {
                // TODO: check if this works...
                var mi = TypeFns.GetMethodByExample((String s) => String.Concat(s, "xxx"));
                return(Expression.Call(mi, exprs[0], exprs[1]));
            }
            else if (FnName == "substring")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.Substring(1, 5));
                return(Expression.Call(exprs[0], mi, exprs.Skip(1)));
            }
            else if (FnName == "replace")
            {
                // TODO: check if this works...
                var mi = TypeFns.GetMethodByExample((String s) => s.Replace("aaa", "bbb"));
                return(Expression.Call(exprs[0], mi, exprs[1], exprs[2]));
            }
            else if (FnName == "year")
            {
                return(GetPropertyExpression(expr, "Year", typeof(int)));
            }
            else if (FnName == "month")
            {
                return(GetPropertyExpression(expr, "Month", typeof(int)));
            }
            else if (FnName == "day")
            {
                return(GetPropertyExpression(expr, "Day", typeof(int)));
            }
            else if (FnName == "hour")
            {
                return(GetPropertyExpression(expr, "Hour", typeof(int)));
            }
            else if (FnName == "minute")
            {
                return(GetPropertyExpression(expr, "Minute", typeof(int)));
            }
            else if (FnName == "second")
            {
                return(GetPropertyExpression(expr, "Second", typeof(int)));
            }
            else if (FnName == "round")
            {
                // TODO: confirm that this works - is using static method.
                var mi = TypeFns.GetMethodByExample((Double d) => Math.Round(d));
                return(Expression.Call(mi, expr));
            }
            else if (FnName == "ceiling")
            {
                var mi = TypeFns.GetMethodByExample((Double d) => Math.Ceiling(d));
                return(Expression.Call(mi, expr));
            }
            else if (FnName == "floor")
            {
                var mi = TypeFns.GetMethodByExample((Double d) => Math.Floor(d));
                return(Expression.Call(mi, expr));
            }
            else if (FnName == "startswith")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.StartsWith("xxx"));
                return(Expression.Call(exprs[0], mi, exprs[1]));
            }
            else if (FnName == "endsWith")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.EndsWith("xxx"));
                return(Expression.Call(exprs[0], mi, exprs[1]));
            }
            else if (FnName == "substringof")
            {
                var mi = TypeFns.GetMethodByExample((String s) => s.Contains("xxx"));
                return(Expression.Call(exprs[0], mi, exprs[1]));
            }
            else
            {
                throw new Exception("Unable to locate Fn: " + FnName);
            }
        }
        private static BasePredicate PredicateFromKeyValue(String key, Object value)
        {
            Operator op = Operator.FromString(key);

            if (op != null)
            {
                if (op.OpType == OperatorType.AndOr)
                {
                    var preds2 = PredicatesFromObject(value);
                    return(new AndOrPredicate(op, preds2));
                }
                else if (op.OpType == OperatorType.Unary)
                {
                    BasePredicate pred = PredicateFromObject(value);
                    return(new UnaryPredicate(op, pred));
                }
                else
                {
                    throw new Exception("Invalid operator in context: " + key);
                }
            }

            if (value == null || TypeFns.IsPredefinedType(value.GetType()))
            {
                return(new BinaryPredicate(BinaryOperator.Equals, key, value));
            }
            else if (value is IDictionary <string, object> && ((IDictionary <string, object>)value).ContainsKey("value"))
            {
                return(new BinaryPredicate(BinaryOperator.Equals, key, value));
            }

            if (!(value is Dictionary <string, object>))
            {
                throw new Exception("Unable to resolve value associated with key:" + key);
            }

            var preds = new List <BasePredicate>();
            var map   = (Dictionary <string, object>)value;


            foreach (var subKey in map.Keys)
            {
                Operator      subOp  = Operator.FromString(subKey);
                Object        subVal = map[subKey];
                BasePredicate pred;
                if (subOp != null)
                {
                    if (subOp.OpType == OperatorType.AnyAll)
                    {
                        BasePredicate subPred = PredicateFromObject(subVal);
                        pred = new AnyAllPredicate(subOp, key, subPred);
                    }
                    else if (subOp.OpType == OperatorType.Binary)
                    {
                        pred = new BinaryPredicate(subOp, key, subVal);
                    }
                    else
                    {
                        throw new Exception("Unable to resolve OperatorType for key: " + subKey);
                    }
                    // next line old check was for null not 'ContainsKey'
                }
                else if (subVal is IDictionary <string, object> && ((IDictionary <string, object>)subVal).ContainsKey("value"))
                {
                    pred = new BinaryPredicate(BinaryOperator.Equals, key, subVal);
                }
                else
                {
                    throw new Exception("Unable to resolve BasePredicate after: " + key);
                }
                preds.Add(pred);
            }
            return(CreateCompoundPredicate(preds));
        }
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            var objResult = context.Result as ObjectResult;

            if (objResult == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var qs = context.HttpContext.Request.QueryString;
            var q  = WebUtility.UrlDecode(qs.Value);

            if (q.Length == 0)
            {
                base.OnActionExecuted(context);
                return;
            }
            q = q.Substring(1, q.Length - 2);


            var eq      = new EntityQuery(q);
            var eleType = TypeFns.GetElementType(objResult.Value.GetType());

            eq.Validate(eleType);
            // TODO: handle IEnumerable as well.
            var result      = (IQueryable)objResult.Value;
            int?inlineCount = null;

            if (eq.WherePredicate != null)
            {
                result = QueryBuilder.ApplyWhere(result, eleType, eq.WherePredicate);
            }

            if (eq.IsInlineCountEnabled)
            {
                inlineCount = (int)Queryable.Count((dynamic)result);
            }

            if (eq.OrderByClause != null)
            {
                result = QueryBuilder.ApplyOrderBy(result, eleType, eq.OrderByClause);
            }

            if (eq.SkipCount.HasValue)
            {
                result = QueryBuilder.ApplySkip(result, eleType, eq.SkipCount.Value);
            }

            if (eq.TakeCount.HasValue)
            {
                result = QueryBuilder.ApplyTake(result, eleType, eq.TakeCount.Value);
            }

            if (eq.SelectClause != null)
            {
                result = QueryBuilder.ApplySelect(result, eleType, eq.SelectClause);
            }

            if (eq.ExpandClause != null)
            {
                eq.ExpandClause.PropertyPaths.ToList().ForEach(expand => {
                    result = ((dynamic)result).Include(expand.Replace('/', '.'));
                });
            }

            if (objResult.Value != result)
            {
                // if a select or expand was encountered we need to
                // execute the DbQueries here, so that any exceptions thrown can be properly returned.
                // if we wait to have the query executed within the serializer, some exceptions will not
                // serialize properly.
                var listResult = Enumerable.ToList((dynamic)result);
                var qr         = new QueryResult(listResult, inlineCount);
                context.Result = new ObjectResult(qr);
            }


            base.OnActionExecuted(context);
        }
        private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect)
        {
            // backingStore will be null if not allowed to overwrite the entity.
            var backingStore   = (targetAspect == null) ? null : targetAspect.BackingStore;
            var dict           = (IDictionary <String, JToken>)nodeContext.Node;
            var structuralType = nodeContext.StructuralType;
            // needs to be the current namingConvention
            var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention;

            dict.ForEach(kvp => {
                var key  = nc.ServerPropertyNameToClient(kvp.Key, structuralType);
                var prop = structuralType.GetProperty(key);
                if (prop != null)
                {
                    if (prop.IsDataProperty)
                    {
                        if (backingStore != null)
                        {
                            var dp = (DataProperty)prop;
                            if (dp.IsComplexProperty)
                            {
                                var newCo     = (IComplexObject)kvp.Value.ToObject(dp.ClrType);
                                var co        = (IComplexObject)backingStore[key];
                                var coBacking = co.ComplexAspect.BackingStore;
                                newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
                                    coBacking[kvp2.Key] = kvp2.Value;
                                });
                            }
                            else
                            {
                                var val = kvp.Value;
                                if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType))
                                {
                                    // this can only happen if the client is nonnullable but the server is nullable.
                                    backingStore[key] = dp.DefaultValue;
                                }
                                else if (dp.IsEnumType || (dp.DataType.ClrType == typeof(TimeSpan)))
                                {
                                    backingStore[key] = val.ToObject(dp.ClrType, _customSerializer);
                                }
                                else
                                {
                                    backingStore[key] = val.ToObject(dp.ClrType);
                                }
                            }
                        }
                    }
                    else
                    {
                        // prop is a ComplexObject
                        var np = (NavigationProperty)prop;

                        if (kvp.Value.HasValues)
                        {
                            NodeContext newContext;
                            if (np.IsScalar)
                            {
                                var nestedOb = (JObject)kvp.Value;
                                newContext   = new NodeContext()
                                {
                                    Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np
                                };
                                var entity = (IEntity)CreateAndPopulate(newContext);
                                if (backingStore != null)
                                {
                                    backingStore[key] = entity;
                                }
                            }
                            else
                            {
                                var nestedArray = (JArray)kvp.Value;
                                var navSet      = (INavigationSet)TypeFns.CreateGenericInstance(typeof(NavigationSet <>), prop.ClrType);

                                nestedArray.Cast <JObject>().ForEach(jo => {
                                    newContext = new NodeContext()
                                    {
                                        Node = jo, ObjectType = prop.ClrType, StructuralProperty = np
                                    };
                                    var entity = (IEntity)CreateAndPopulate(newContext);
                                    navSet.Add(entity);
                                });
                                // add to existing nav set if there is one otherwise just set it.
                                object tmp;
                                if (backingStore.TryGetValue(key, out tmp))
                                {
                                    var backingNavSet = (INavigationSet)tmp;
                                    navSet.Cast <IEntity>().ForEach(e => backingNavSet.Add(e));
                                }
                                else
                                {
                                    navSet.NavigationProperty = np;
                                    navSet.ParentEntity       = targetAspect.Entity;
                                    backingStore[key]         = navSet;
                                }
                            }
                        }
                        else
                        {
                            // do nothing
                            //if (!np.IsScalar) {
                            //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
                            //} else {
                            //  return null;
                            //}
                        }
                    }
                }
                else
                {
                    if (backingStore != null)
                    {
                        backingStore[key] = kvp.Value.ToObject <Object>();
                    }
                }
            });
        }
Exemple #17
0
        public override void OnActionExecuted(HttpActionExecutedContext context)
        {
            var qs = QueryFns.ExtractAndDecodeQueryString(context);

            if (qs == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var queryable = QueryFns.ExtractQueryable(context);

            if (queryable == null)
            {
                base.OnActionExecuted(context);
                return;
            }

            var eq      = new EntityQuery(qs);
            var eleType = TypeFns.GetElementType(queryable.GetType());

            eq.Validate(eleType);


            int?inlineCount = null;

            var originalQueryable = queryable;

            queryable = eq.ApplyWhere(queryable, eleType);

            IFutureValue <int> inlineCountFuture = null;

            if (eq.IsInlineCountEnabled)
            {
                if (UseFuture)
                {
                    var countExpr = GetCountExpressionMethod.MakeGenericMethod(eleType).Invoke(this, new object[0]);
                    inlineCountFuture = (IFutureValue <int>)ToFutureValueMethod.MakeGenericMethod(eleType, typeof(int))
                                        .Invoke(null, new[] { queryable, countExpr });
                }
                else
                {
                    inlineCount = (int)Queryable.Count((dynamic)queryable);
                }
            }

            queryable = eq.ApplyOrderBy(queryable, eleType);
            queryable = eq.ApplySkip(queryable, eleType);
            queryable = eq.ApplyTake(queryable, eleType);
            queryable = eq.ApplySelect(queryable, eleType);
            queryable = eq.ApplyExpand(queryable, eleType);


            if (queryable != originalQueryable)
            {
                // if a select or expand was encountered we need to
                // execute the DbQueries here, so that any exceptions thrown can be properly returned.
                // if we wait to have the query executed within the serializer, some exceptions will not
                // serialize properly.

                dynamic listResult;
                if (UseFuture)
                {
                    var future = ToFutureMethod.MakeGenericMethod(eleType).Invoke(null, new object[] { queryable });
                    listResult = Enumerable.ToList((dynamic)future.GetType().GetMethod("GetEnumerable").Invoke(future, new object[0]));
                }
                else
                {
                    listResult = Enumerable.ToList((dynamic)queryable);
                }

                var qr = new QueryResult(listResult, inlineCountFuture?.Value ?? inlineCount);

                if (CloseSession)
                {
                    var session = GetSession(queryable);
                    if (session != null)
                    {
                        Close(session);
                    }
                }

                context.Response = context.Request.CreateResponse(HttpStatusCode.OK, qr);
            }

            base.OnActionExecuted(context);
        }