public override ProjectionExpression GetQueryExpression(MappingEntity entity) { var tables = this.mapping.GetTables(entity); if (tables.Count <= 1) { return(base.GetQueryExpression(entity)); } var aliases = new Dictionary <string, TableAlias>(); MappingTable rootTable = tables.Single(ta => !this.mapping.IsExtensionTable(ta)); var tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(rootTable)); aliases.Add(this.mapping.GetAlias(rootTable), tex.Alias); Expression source = tex; foreach (MappingTable table in tables.Where(t => this.mapping.IsExtensionTable(t))) { TableAlias joinedTableAlias = new TableAlias(); string extensionAlias = this.mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); List <string> keyColumns = this.mapping.GetExtensionKeyColumnNames(table).ToList(); List <MemberInfo> relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToList(); string relatedAlias = this.mapping.GetExtensionRelatedAlias(table); TableAlias relatedTableAlias; aliases.TryGetValue(relatedAlias, out relatedTableAlias); TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, this.mapping.GetTableName(table)); Expression cond = null; for (int i = 0, n = keyColumns.Count; i < n; i++) { var memberType = TypeHelper.GetMemberType(relatedMembers[i]); var colType = this.GetColumnType(entity, relatedMembers[i]); var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, this.mapping.GetColumnName(entity, relatedMembers[i])); var joinedColumn = new ColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]); var eq = joinedColumn.Equal(relatedColumn); cond = (cond != null) ? cond.And(eq) : eq; } source = new JoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond); } var columns = new List <ColumnDeclaration>(); this.GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null); var existingAliases = aliases.Values.ToArray(); Expression projector = this.GetEntityExpression(root, entity); var selectAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, root.Alias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, root, null), pc.Projector); return((ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType)); }
/// <summary> /// Get an expression for a mapped property relative to a root expression. /// The root is either a TableExpression or an expression defining an entity instance. /// </summary> /// <param name="root"></param> /// <param name="member"></param> /// <returns></returns> public virtual Expression GetMemberExpression(Expression root, MemberInfo member) { if (this.IsRelationship(member)) { Type rowType = this.GetRelatedType(member); ProjectionExpression projection = this.GetTableQuery(rowType); // make where clause for joining back to 'root' List <MemberInfo> declaredTypeMembers; List <MemberInfo> associatedMembers; this.GetAssociationKeys(member, out declaredTypeMembers, out associatedMembers); Expression where = null; for (int i = 0, n = associatedMembers.Count; i < n; i++) { Expression equal = Expression.Equal( this.GetMemberExpression(projection.Projector, associatedMembers[i]), this.GetMemberExpression(root, declaredTypeMembers[i]) ); where = (where != null) ? Expression.And(where, equal) : equal; } TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.Language.CanBeColumn, projection.Projector, null, newAlias, projection.Source.Alias); LambdaExpression aggregator = this.GetAggregator(TypeHelper.GetMemberType(member), typeof(IEnumerable <>).MakeGenericType(pc.Projector.Type)); return(new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, projection.Source, where), pc.Projector, aggregator )); } else { TableExpression table = root as TableExpression; if (table != null) { if (this.IsColumn(member)) { string columnName = this.GetColumnName(member); if (!string.IsNullOrEmpty(columnName)) { return(new ColumnExpression(TypeHelper.GetMemberType(member), table.Alias, this.GetColumnName(member))); } else { return(root); } } else { return(this.GetTypeProjection(root, TypeHelper.GetMemberType(member))); } } else { return(QueryBinder.BindMember(root, member)); } } }
static internal ProjectedColumns ProjectColumns(Expression projector, Alias newAlias, bool isGroupKey = false, bool selectTrivialColumns = false) { var candidates = DbExpressionNominator.Nominate(projector, out Expression newProj, isGroupKey: isGroupKey); ColumnProjector cp = new ColumnProjector(candidates, newAlias, selectTrivialColumns); Expression e = cp.Visit(newProj); return(new ProjectedColumns(e, cp.generator.Columns.NotNull().ToReadOnly())); }
protected override Expression VisitMethodCall(MethodCallExpression m) { if (m.Method.DeclaringType == typeof(Queryable)) { this.Visit(m.Arguments[0]); if (m.Method.Name == "Where") { var expression = LeafEvaluator.PartialEval(m.Arguments[1]); AddPrefix("filter"); LambdaExpression lambda = (LambdaExpression)StripQuotes(expression); this.Visit(lambda.Body); return(m); } else if (m.Method.Name == "Take") { AddPrefix("top"); this.Visit(m.Arguments[1]); return(m); } else if (m.Method.Name == "Skip") { AddPrefix("skip"); this.Visit(m.Arguments[1]); return(m); } else if (m.Method.Name == "OrderBy") { AddPrefix("orderby"); LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]); this.Visit(lambda.Body); return(m); } else if (m.Method.Name == "OrderByDescending") { AddPrefix("orderby"); LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]); this.Visit(lambda.Body); _sb.Append(" desc"); return(m); } else if (m.Method.Name == "Select") { LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]); ColumnProjection projection = new ColumnProjector().ProjectColumns(lambda); AddPrefix("select"); _sb.Append(projection.Columns); this._projection = projection; return(m); } } throw new NotSupportedException(string.Format("The method '{0}' is not supported", m.Method.Name)); }
/// <summary> /// The query language specific type for the column /// </summary> /// <param name="entity">The entity.</param> /// <param name="member">The member.</param> /// <returns></returns> //public virtual QueryType GetColumnType(MappingEntity entity, MemberInfo member) //{ // return this.translator.Linguist.Language.TypeSystem.GetColumnType(TypeHelper.GetMemberType(member)); //} /// <summary> /// Get a query expression that selects all entities from a table /// </summary> /// <param name="entity">The entity.</param> /// <returns></returns> public override ProjectionExpression GetQueryExpression(MappingEntity entity) { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); Expression projector = this.GetEntityExpression(table, entity); var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, projector, null, selectAlias, tableAlias); var proj = new ProjectionExpression(new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector); return((ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType)); }
/// <summary> /// Get a query expression that selects all entities from a table /// </summary> /// <param name="rowType"></param> /// <returns></returns> public virtual ProjectionExpression GetTableQuery(Type rowType) { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var table = new TableExpression(tableAlias, this.GetTableName(rowType)); Expression projector = this.GetTypeProjection(table, rowType); var pc = ColumnProjector.ProjectColumns(this.Language.CanBeColumn, projector, null, selectAlias, tableAlias); return(new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector )); }
public override ProjectionExpression GetQueryExpression(MappingEntity entity) { CompositiveMappingEntity mme = (CompositiveMappingEntity)entity; if (mme.Table == null || string.IsNullOrEmpty(mme.Table.View)) { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var columns = new List <ColumnDeclaration>(); var aliases = new Dictionary <string, TableAlias>(); var table = new TableExpression(tableAlias, entity, (this.Mapping as BasicMapping).GetTableName(entity)); this.GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, table, null); Expression projector = this.GetEntityExpression(table, entity); var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, tableAlias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector ); return((ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType)); } else { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var columns = new List <ColumnDeclaration>(); var aliases = new Dictionary <string, TableAlias>(); var table = new TableExpression(tableAlias, entity, mme.Table.View); ColumnDeclaration cd = new ColumnDeclaration("*", "", new AllColumnExpression(tableAlias), new DbQueryType(SqlDbType.Variant, false, 0, 0, 0)); columns.Add(cd); SelectExpression root = new SelectExpression(new TableAlias(), columns, table, null); Expression projector = this.GetEntityExpression(table, entity); //var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, tableAlias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, columns, table, null), projector ); return((ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType)); } }
internal Expression GetUpdateResult(IEntityMapping mapping, Expression instance, LambdaExpression selector) { var tq = this.GetQueryExpression(mapping); Expression where = this.GetIdentityCheck(tq.Select, mapping, instance); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], tq.Projector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(selection, null, newAlias, tq.Select.Alias); return(new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, tq.Select, where), pc.Projector, Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable <>).MakeGenericType(selector.Body.Type)) )); }
protected override Expression VisitJoin(JoinExpression join) { join = (JoinExpression)base.VisitJoin(join); if (join.Join == JoinType.CrossApply || join.Join == JoinType.OuterApply) { if (join.Right is TableExpression) { return(new JoinExpression(JoinType.CrossJoin, join.Left, join.Right, null)); } else { SelectExpression select = join.Right as SelectExpression; // Only consider rewriting cross apply if // 1) right side is a select // 2) other than in the where clause in the right-side select, no left-side declared aliases are referenced // 3) and has no behavior that would change semantics if the where clause is removed (like groups, aggregates, take, skip, etc). // Note: it is best to attempt this after redundant subqueries have been removed. if (select != null && select.Take == null && select.Skip == null && !AggregateChecker.HasAggregates(select) && (select.GroupBy == null || select.GroupBy.Count == 0)) { SelectExpression selectWithoutWhere = select.SetWhere(null); HashSet <TableAlias> referencedAliases = ReferencedAliasGatherer.Gather(selectWithoutWhere); HashSet <TableAlias> declaredAliases = DeclaredAliasGatherer.Gather(join.Left); referencedAliases.IntersectWith(declaredAliases); if (referencedAliases.Count == 0) { Expression where = select.Where; select = selectWithoutWhere; var pc = ColumnProjector.ProjectColumns(this.language, where, select.Columns, select.Alias, DeclaredAliasGatherer.Gather(select.From)); select = select.SetColumns(pc.Columns); where = pc.Projector; JoinType jt = (where == null) ? JoinType.CrossJoin : (join.Join == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftOuter); return(new JoinExpression(jt, join.Left, select, where)); } } } } return(join); }
public virtual Expression GetMemberExpression(Expression root, IEntityMapping mapping, IMemberMapping mm) { var m = mm.Member; if (mm.IsRelationship) { IEntityMapping relatedEntity = mm.RelatedEntity; ProjectionExpression projection = this.GetQueryExpression(relatedEntity); // make where clause for joining back to 'root' var thisKeyMembers = mm.ThisKeyMembers; var otherKeyMembers = mm.OtherKeyMembers; Expression where = null; for (int i = 0, n = otherKeyMembers.Length; i < n; i++) { Expression equal = this.GetMemberExpression(projection.Projector, relatedEntity, otherKeyMembers[i]).Equal( this.GetMemberExpression(root, mapping, thisKeyMembers[i]) ); where = (where != null) ? where.And(equal) : equal; } TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(projection.Projector, null, newAlias, projection.Select.Alias); LambdaExpression aggregator = Aggregator.GetAggregator(mm.MemberType, typeof(IEnumerable <>).MakeGenericType(pc.Projector.Type)); var result = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, projection.Select, where), pc.Projector, aggregator ); return(ApplyPolicy(result, m)); } else { AliasedExpression aliasedRoot = root as AliasedExpression; if (aliasedRoot != null && mm.IsColumn) { return(new ColumnExpression(mm.MemberType, mm.SqlType, aliasedRoot.Alias, mm.ColumnName)); } return(QueryBinder.BindMember(root, m)); } }
protected override Expression VisitProjection(ProjectionExpression proj) { if (isTopLevel) { isTopLevel = false; this.currentSelect = proj.Select; Expression projector = this.Visit(proj.Projector); if (projector != proj.Projector || this.currentSelect != proj.Select) { return(new ProjectionExpression(this.currentSelect, projector, proj.Aggregator)); } return(proj); } if (proj.IsSingleton && this.CanJoinOnServer(this.currentSelect)) { TableAlias newAlias = new TableAlias(); this.currentSelect = this.currentSelect.AddRedundantSelect(this.language, newAlias); // remap any references to the outer select to the new alias; SelectExpression source = (SelectExpression)ColumnMapper.Map(proj.Select, newAlias, this.currentSelect.Alias); // add outer-join test ProjectionExpression pex = this.language.AddOuterJoinTest(new ProjectionExpression(source, proj.Projector)); var pc = ColumnProjector.ProjectColumns(this.language, pex.Projector, this.currentSelect.Columns, this.currentSelect.Alias, newAlias, proj.Select.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, this.currentSelect.From, pex.Select, null); this.currentSelect = new SelectExpression(this.currentSelect.Alias, pc.Columns, join, null); return(this.Visit(pc.Projector)); } var saveTop = this.isTopLevel; var saveSelect = this.currentSelect; this.isTopLevel = true; this.currentSelect = null; Expression result = base.VisitProjection(proj); this.isTopLevel = saveTop; this.currentSelect = saveSelect; return(result); }
protected override Expression VisitJoin(SqlJoinExpression join) { join = (SqlJoinExpression)base.VisitJoin(join); if (join.JoinType == SqlJoinType.CrossApply || join.JoinType == SqlJoinType.OuterApply) { if (join.Right is SqlTableExpression) { return(new SqlJoinExpression(join.Type, SqlJoinType.Cross, join.Left, join.Right, null)); } else { var select = join.Right as SqlSelectExpression; if (select != null && select.Take == null && select.Skip == null && !SqlAggregateChecker.HasAggregates(select) && (select.GroupBy == null || select.GroupBy.Count == 0)) { var selectWithoutWhere = select.ChangeWhere(null); var referencedAliases = SqlReferencedAliasGatherer.Gather(selectWithoutWhere); var declaredAliases = SqlDeclaredAliasGatherer.Gather(join.Left); referencedAliases.IntersectWith(declaredAliases); if (referencedAliases.Count == 0) { var where = select.Where; select = selectWithoutWhere; var pc = ColumnProjector.ProjectColumns(new Nominator(Nominator.CanBeColumn), where, select.Columns, select.Alias, SqlDeclaredAliasGatherer.Gather(select.From)); select = select.ChangeColumns(pc.Columns); where = pc.Projector; var joinType = (where == null) ? SqlJoinType.Cross : (join.JoinType == SqlJoinType.CrossApply ? SqlJoinType.Inner : SqlJoinType.Left); return(new SqlJoinExpression(typeof(void), joinType, join.Left, select, where)); } } } } return(join); }
protected internal override Expression VisitProjection(ProjectionExpression proj) { Expression projector; SelectExpression select = proj.Select; using (binder.SetCurrentSource(proj.Select)) projector = this.Visit(proj.Projector); Alias alias = binder.aliasGenerator.NextSelectAlias(); ProjectedColumns pc = ColumnProjector.ProjectColumns(projector, alias); projector = pc.Projector; select = new SelectExpression(alias, false, null, pc.Columns, select, null, null, null, 0); if (projector != proj.Projector) { return(new ProjectionExpression(select, projector, proj.UniqueFunction, proj.Type)); } return(proj); }
public virtual ProjectionExpression GetQueryExpression(IEntityMapping mapping) { Expression projector; TableAlias selectAlias; ProjectedColumns pc; ProjectionExpression proj; var tableAlias = new TableAlias(); selectAlias = new TableAlias(); var table = new TableExpression(tableAlias, mapping); projector = this.GetEntityExpression(table, mapping); pc = ColumnProjector.ProjectColumns(projector, null, selectAlias, tableAlias); proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector ); return((ProjectionExpression)ApplyPolicy(proj, mapping.EntityType)); }
public virtual Expression GetInsertResult(IEntityMapping mapping, Expression instance, LambdaExpression selector, Dictionary <MemberInfo, Expression> map) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, mapping); var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable <>).MakeGenericType(selector.Body.Type)); Expression where = null; DeclarationCommand genIdCommand = null; var generatedIds = mapping.PrimaryKeys.Where(m => m.IsPrimaryKey && m.IsGenerated).ToList(); if (generatedIds.Count > 0) { if (map == null || !generatedIds.Any(m => map.ContainsKey(m.Member))) { var localMap = new Dictionary <MemberInfo, Expression>(); genIdCommand = this.GetGeneratedIdCommand(mapping, generatedIds, localMap); map = localMap; } // is this just a retrieval of one generated id member? var mex = selector.Body as MemberExpression; if (mex != null) { var id = mapping.Get(mex.Member); if (id != null && id.IsPrimaryKey && id.IsGenerated) { if (genIdCommand != null) { // just use the select from the genIdCommand return(new ProjectionExpression( genIdCommand.Source, new ColumnExpression(mex.Type, genIdCommand.Variables[0].SqlType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator )); } else { TableAlias alias = new TableAlias(); var colType = id.SqlType; return(new ProjectionExpression( new SelectExpression(alias, new[] { new ColumnDeclaration("", map[mex.Member], colType) }, null, null), new ColumnExpression(mex.Member.GetMemberType(), colType, alias, ""), aggregator )); } } where = generatedIds.Select((m, i) => this.GetMemberExpression(tex, mapping, m.Member).Equal(map[m.Member]) ).Aggregate((x, y) => x.And(y)); } } else { where = this.GetIdentityCheck(tex, mapping, instance); } Expression typeProjector = this.GetEntityExpression(tex, mapping); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(selection, null, newAlias, tableAlias); var pe = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, tex, where), pc.Projector, aggregator ); if (genIdCommand != null) { return(new BlockCommand(genIdCommand, pe)); } return(pe); }
protected override Expression VisitProjection(ProjectionExpression proj) { SelectExpression save = this.currentSelect; this.currentSelect = proj.Select; try { if (!this.isTopLevel) { if (this.CanJoinOnClient(this.currentSelect)) { // make a query that combines all the constraints from the outer queries into a single select SelectExpression newOuterSelect = (SelectExpression)QueryDuplicator.Duplicate(save); // remap any references to the outer select to the new alias; SelectExpression newInnerSelect = (SelectExpression)ColumnMapper.Map(proj.Select, newOuterSelect.Alias, save.Alias); // add outer-join test ProjectionExpression newInnerProjection = this.language.AddOuterJoinTest(new ProjectionExpression(newInnerSelect, proj.Projector)); newInnerSelect = newInnerProjection.Select; Expression newProjector = newInnerProjection.Projector; TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.language, newProjector, null, newAlias, newOuterSelect.Alias, newInnerSelect.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, newOuterSelect, newInnerSelect, null); SelectExpression joinedSelect = new SelectExpression(newAlias, pc.Columns, join, null, null, null, proj.IsSingleton, null, null, false); // apply client-join treatment recursively this.currentSelect = joinedSelect; newProjector = this.Visit(pc.Projector); // compute keys (this only works if join condition was a single column comparison) List <Expression> outerKeys = new List <Expression>(); List <Expression> innerKeys = new List <Expression>(); if (this.GetEquiJoinKeyExpressions(newInnerSelect.Where, newOuterSelect.Alias, outerKeys, innerKeys)) { // outerKey needs to refer to the outer-scope's alias var outerKey = outerKeys.Select(k => ColumnMapper.Map(k, save.Alias, newOuterSelect.Alias)); // innerKey needs to refer to the new alias for the select with the new join var innerKey = innerKeys.Select(k => ColumnMapper.Map(k, joinedSelect.Alias, ((ColumnExpression)k).Alias)); ProjectionExpression newProjection = new ProjectionExpression(joinedSelect, newProjector, proj.Aggregator); return(new ClientJoinExpression(newProjection, outerKey, innerKey)); } } else { bool saveJoin = this.canJoinOnClient; this.canJoinOnClient = false; var result = base.VisitProjection(proj); this.canJoinOnClient = saveJoin; return(result); } } else { this.isTopLevel = false; } return(base.VisitProjection(proj)); } finally { this.currentSelect = save; } }
/// <summary> /// Visits the children of the <see cref="T:System.Linq.Expressions.MethodCallExpression"/>. /// </summary> /// <param name="node">The expression to visit.</param> /// <returns> /// The modified expression, if it or any subexpression was modified; otherwise, returns the /// original expression. /// </returns> /// <exception cref="NotSupportedException"></exception> protected override Expression?VisitMethodCall(MethodCallExpression node) { if (node is null) { return(node); } if (node.Method.DeclaringType == typeof(Queryable)) { if (node.Method.Name == "Where") { node = (MethodCallExpression)Evaluator.PartialEval(node); Visit(node.Arguments[0]); var lambda = (LambdaExpression)StripQuotes(node.Arguments[1]); var CurrentClause = new WhereVisitor <TObject>(Count).WhereProjection(lambda.Body); ++Count; foreach (var Source in Builders.Keys) { Builders[Source].WhereClause.Combine(CurrentClause.Copy()); } return(node); } if (node.Method.Name == "Select") { Visit(node.Arguments[0]); var lambda = (LambdaExpression)StripQuotes(node.Arguments[1]); var Columns = new ColumnProjector().ProjectColumns(lambda.Body); foreach (var Source in Builders.Keys) { var ParentMappings = Source.GetChildMappings(typeof(TObject)) .SelectMany(x => Source.GetParentMapping(x.ObjectType)) .Distinct(); foreach (var Column in Columns) { if (ParentMappings.Any(x => x.ContainsProperty(Column.Name))) { Builders[Source].SelectValues.Add(Column); } } } return(node); } if (node.Method.Name == "ThenBy" || node.Method.Name == "OrderBy" || node.Method.Name == "OrderByDescending" || node.Method.Name == "ThenByDescending") { Visit(node.Arguments[0]); var lambda = (LambdaExpression)StripQuotes(node.Arguments[1]); var Columns = new ColumnProjector().ProjectColumns(lambda.Body); foreach (var Source in Builders.Keys) { var ParentMappings = Source.GetChildMappings(typeof(TObject)) .SelectMany(x => Source.GetParentMapping(x.ObjectType)) .Distinct(); foreach (var Column in Columns) { if (ParentMappings.Any(x => x.ContainsProperty(Column.Name))) { Builders[Source].OrderByValues.Add(new OrderByClause(Builders[Source].OrderByValues.Count, Column, node.Method.Name.Contains("Descending", StringComparison.OrdinalIgnoreCase) ? Direction.Descending : Direction.Ascending)); } } } return(node); } if (node.Method.Name == "Distinct") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Distinct = true; } return(node); } if (node.Method.Name == "First" || node.Method.Name == "FirstOrDefault" || node.Method.Name == "Single" || node.Method.Name == "SingleOrDefault") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Top = 1; } return(node); } if (node.Method.Name == "Take") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Top = (int)((node.Arguments[1] as ConstantExpression)?.Value ?? 1); } return(node); } if (node.Method.Name == "Skip") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Skip = (int)((node.Arguments[1] as ConstantExpression)?.Value ?? 1); } return(node); } if (node.Method.Name == "Count") { Visit(node.Arguments[0]); foreach (var Source in Builders.Keys) { Builders[Source].Count = true; } return(node); } } throw new NotSupportedException($"The method '{node.Method.Name}' is not supported."); }