// <summary> // Collapses outerProject(outerProjection(innerProject(innerNew))) // </summary> private static DbExpression CollapseNestedProjection(DbExpression expression) { var outerProject = (DbProjectExpression)expression; var outerProjection = outerProject.Projection; var innerProject = (DbProjectExpression)outerProject.Input.Expression; var innerNew = (DbNewInstanceExpression)innerProject.Projection; // get membername -> expression bindings for the inner select so that we know how map property // references to the inner projection var bindings = new Dictionary <string, DbExpression>(innerNew.Arguments.Count); var innerResultTypeUsage = innerNew.ResultType; var innerResultType = (RowType)innerResultTypeUsage.EdmType; for (var ordinal = 0; ordinal < innerResultType.Members.Count; ordinal++) { bindings[innerResultType.Members[ordinal].Name] = innerNew.Arguments[ordinal]; } // initialize an expression visitor that knows how to map arguments to the outer projection // to the inner projection source var collapser = new ProjectionCollapser(bindings, outerProject.Input); // replace all property references to the inner projection var replacementOuterProjection = collapser.CollapseProjection(outerProjection); // make sure the collapsing was successful; if not, give up on simplification if (collapser.IsDoomed) { return(null); } // set replacement value so that the expression replacer infrastructure can substitute // the collapsed projection in the expression tree // continue collapsing projection until the pattern no longer matches var replacementOuterProject = innerProject.Input.Project(replacementOuterProjection); return(replacementOuterProject); }
/// <summary> /// Collapses outerProject(outerProjection(innerProject(innerNew))) /// </summary> private static DbExpression CollapseNestedProjection(DbExpression expression) { DbProjectExpression outerProject = (DbProjectExpression)expression; DbExpression outerProjection = outerProject.Projection; DbProjectExpression innerProject = (DbProjectExpression)outerProject.Input.Expression; DbNewInstanceExpression innerNew = (DbNewInstanceExpression)innerProject.Projection; // get membername -> expression bindings for the inner select so that we know how map property // references to the inner projection Dictionary<string, DbExpression> bindings = new Dictionary<string, DbExpression>(innerNew.Arguments.Count); TypeUsage innerResultTypeUsage = innerNew.ResultType; RowType innerResultType = (RowType)innerResultTypeUsage.EdmType; for (int ordinal = 0; ordinal < innerResultType.Members.Count; ordinal++) { bindings[innerResultType.Members[ordinal].Name] = innerNew.Arguments[ordinal]; } // initialize an expression visitor that knows how to map arguments to the outer projection // to the inner projection source ProjectionCollapser collapser = new ProjectionCollapser(bindings, outerProject.Input); // replace all property references to the inner projection var replacementOuterProjection = collapser.CollapseProjection(outerProjection); // make sure the collapsing was successful; if not, give up on simplification if (collapser.IsDoomed) { return null; } // set replacement value so that the expression replacer infrastructure can substitute // the collapsed projection in the expression tree // continue collapsing projection until the pattern no longer matches DbProjectExpression replacementOuterProject = innerProject.Input.Project(replacementOuterProjection); return replacementOuterProject; }