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