public ODataExpression Translate(Expression linq, out IQueryable rootQuery, out ResultTranslator resultTranslator) { this._isInsideQuery = false; this._rootQuery = null; this._resultTranslator = null; this._memberAndParameterTranslator = new MemberAndParameterTranslator(this); // normalize away ODataRow constructs var normalized = ODataEntity.Normalize(linq); var translated = this.TranslateInternal(normalized); if (translated.Kind == ODataExpressionKind.Query) { var referencedPaths = this._memberAndParameterTranslator.GetReferencedMemberPathsInFinalProjection(); if (referencedPaths != null) { var selectColumns = referencedPaths.Select(p => p.Aggregate(default(ODataMemberAccessExpression), (e, m) => ODataExpression.MemberAccess(e, (PropertyInfo)m))) .Select(ma => ODataExpression.SelectColumn(ma, allColumns: ma.Type == ODataExpressionType.Complex)); translated = ((ODataQueryExpression)translated).Update(select: selectColumns); } } rootQuery = this._rootQuery; var projection = this._memberAndParameterTranslator.GetFinalProjection(); var finalTranslator = this._resultTranslator ?? ((values, count) => values); if (projection != null) { var selectMethod = Helpers.GetMethod((IEnumerable <object> e) => e.Select(o => o)) .GetGenericMethodDefinition() .MakeGenericMethod(projection.Type.GetGenericArguments(typeof(Func <,>))); // restores any ODataRow constructs that were normalized away, since we need to be able to compile and run the projection // (i. e. fake ODataRow property accesses don't run when compiled) var denormalizedProjection = (LambdaExpression)ODataEntity.Denormalize(projection); Func <object, object> queryTranslator = enumerable => selectMethod.Invoke(null, new[] { enumerable, denormalizedProjection.Compile() }); resultTranslator = (values, count) => finalTranslator((IEnumerable)queryTranslator(values), count); } else { resultTranslator = finalTranslator; } return(translated); }
public ODataExpression Translate(Expression linq, out IQueryable rootQuery, out ResultTranslator resultTranslator) { this._isInsideQuery = false; this._rootQuery = null; this._resultTranslator = null; this._memberAndParameterTranslator = new MemberAndParameterTranslator(this); // normalize away ODataRow constructs var normalized = ODataEntity.Normalize(linq); var translated = this.TranslateInternal(normalized); if (translated.Kind == ODataExpressionKind.Query) { var referencedPaths = this._memberAndParameterTranslator.GetReferencedMemberPathsInFinalProjection(); if (referencedPaths != null) { var selectColumns = referencedPaths.Select(p => p.Aggregate(default(ODataMemberAccessExpression), (e, m) => ODataExpression.MemberAccess(e, (PropertyInfo)m))) .Select(ma => ODataExpression.SelectColumn(ma, allColumns: ma.Type == ODataExpressionType.Complex)); translated = ((ODataQueryExpression)translated).Update(select: selectColumns); } } rootQuery = this._rootQuery; var projection = this._memberAndParameterTranslator.GetFinalProjection(); var finalTranslator = this._resultTranslator ?? ((values, count) => values); if (projection != null) { var selectMethod = Helpers.GetMethod((IEnumerable<object> e) => e.Select(o => o)) .GetGenericMethodDefinition() .MakeGenericMethod(projection.Type.GetGenericArguments(typeof(Func<,>))); // restores any ODataRow constructs that were normalized away, since we need to be able to compile and run the projection // (i. e. fake ODataRow property accesses don't run when compiled) var denormalizedProjection = (LambdaExpression)ODataEntity.Denormalize(projection); Func<object, object> queryTranslator = enumerable => selectMethod.Invoke(null, new[] { enumerable, denormalizedProjection.Compile() }); resultTranslator = (values, count) => finalTranslator((IEnumerable)queryTranslator(values), count); } else { resultTranslator = finalTranslator; } return translated; }