예제 #1
0
        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;
        }