public override Expression GetDeleteExpression(MappingEntity entity, Expression instance, LambdaExpression deleteCheck) { var tables = this.mapping.GetTables(entity); if (tables.Count < 2) { return base.GetDeleteExpression(entity, instance, deleteCheck); } var commands = new List<Expression>(); foreach (var table in this.GetDependencyOrderedTables(entity).Reverse()) { TableExpression tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(table)); var where = this.GetIdentityCheck(tex, entity, instance); commands.Add(new DeleteCommand(tex, where)); } Expression block = new BlockCommand(commands); if (deleteCheck != null) { var test = this.GetEntityStateTest(entity, instance, deleteCheck); return new IFCommand(test, block, null); } return block; }
protected override Expression VisitTable(TableExpression table) { var columns = CurrentScope.Keys.Where(ce => ce.Alias == table.Alias).ToList(); CurrentScope.SetRange(columns, columns.Cast<Expression>()); return table; }
public override Expression GetDeleteExpression(MappingEntity entity, Expression instance, LambdaExpression deleteCheck) { TableExpression table = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(entity)); Expression where = null; if (instance != null) { where = this.GetIdentityCheck(table, entity, instance); } if (deleteCheck != null) { Expression row = this.GetEntityExpression(table, entity); Expression pred = DbExpressionReplacer.Replace(deleteCheck.Body, deleteCheck.Parameters[0], row); where = (where != null) ? where.And(pred) : pred; } return new DeleteCommand(table, where); }
public SqlStatement TranslateNonQuery(DynamicLinqCommand command) { var translCtx = new TranslationContext(_dbModel, command); // convert lambda params into an initial set of ExternalValueExpression objects; foreach (var prm in command.Lambda.Parameters) { var inpParam = new ExternalValueExpression(prm); translCtx.ExternalValues.Add(inpParam); } //Analyze/transform base select query var selectExpr = TranslateSelectExpression(command, translCtx); var targetEnt = command.UpdateEntity; var targetTable = _dbModel.GetTable(targetEnt.EntityType); var nonQueryCmd = new NonQueryLinqCommand(command, targetTable, selectExpr); // Analyze base query output expression var targetTableExpr = new TableExpression(targetTable); var readerBody = selectExpr.RowReaderLambda.Body; switch (nonQueryCmd.Operation) { case LinqOperation.Update: case LinqOperation.Insert: Util.Check(readerBody.NodeType == ExpressionType.New, "Query for LINQ {0} command must return New object", nonQueryCmd.Operation); var newExpr = readerBody as NewExpression; var outValues = selectExpr.Operands.ToList(); for (int i = 0; i < newExpr.Members.Count; i++) { var memberName = newExpr.Members[i].Name; var memberInfo = targetEnt.GetMember(memberName); Util.Check(memberInfo != null, "Member {0} not found in entity {1}.", memberName, targetEnt, targetEnt.EntityType); switch (memberInfo.Kind) { case EntityMemberKind.Column: var col = _translator.CreateColumnForMember(targetTableExpr, memberInfo, translCtx); nonQueryCmd.TargetColumns.Add(col.ColumnInfo); nonQueryCmd.SelectOutputValues.Add(outValues[i]); break; case EntityMemberKind.EntityRef: var fromKey = memberInfo.ReferenceInfo.FromKey; Util.Check(fromKey.ExpandedKeyMembers.Count == 1, "References with composite keys are not supported in LINQ non-query operations. Reference: ", memberName); var pkMember = fromKey.ExpandedKeyMembers[0].Member; var col2 = _translator.CreateColumnForMember(targetTableExpr, pkMember, translCtx); nonQueryCmd.TargetColumns.Add(col2.ColumnInfo); nonQueryCmd.SelectOutputValues.Add(outValues[i]); break; default: Util.Throw("Property cannot be used in the context: {0}.", memberName); break; } } break; case LinqOperation.Delete: nonQueryCmd.SelectOutputValues.Add(readerBody); //should return single value - primary key break; } // Build SQL var sqlBuilder = _dbModel.Driver.CreateLinqNonQuerySqlBuilder(_dbModel, nonQueryCmd); var stmt = sqlBuilder.BuildLinqNonQuerySql(); return(stmt); } //method
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); }
protected override Expression VisitTable(TableExpression table) { if (aliasMap.ContainsKey(table.Alias)) return new TableExpression(aliasMap[table.Alias], table.Table); return table; }
protected virtual Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type)); Expression where; DeclarationCommand genIdCommand = null; var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList(); if (generatedIds.Count > 0) { if (map == null || !generatedIds.Any(m => map.ContainsKey(m))) { var localMap = new Dictionary<MemberInfo, Expression>(); genIdCommand = this.GetGeneratedIdCommand(entity, generatedIds.ToList(), localMap); map = localMap; } // is this just a retrieval of one generated id member? var mex = selector.Body as MemberExpression; if (mex != null && this.mapping.IsPrimaryKey(entity, mex.Member) && this.mapping.IsGenerated(entity, mex.Member)) { if (genIdCommand != null) { // just use the select from the genIdCommand return new ProjectionExpression( genIdCommand.Source, new ColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator ); } else { TableAlias alias = new TableAlias(); var colType = this.GetColumnType(entity, mex.Member); return new ProjectionExpression( new SelectExpression(alias, new[] { new ColumnDeclaration("", map[mex.Member], colType) }, null, null), new ColumnExpression(TypeHelper.GetMemberType(mex.Member), colType, alias, ""), aggregator ); } } where = generatedIds.Select((m, i) => this.GetMemberExpression(tex, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = this.GetIdentityCheck(tex, entity, instance); } Expression typeProjector = this.GetEntityExpression(tex, entity); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, 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 abstract Expression VisitTable(TableExpression tableExpression);
private SelectExpression GetCountSelectExpression(SelectExpression select) { BinaryExpression binaryExpression = select.Where as BinaryExpression; if (binaryExpression != null) { ScalarExpression scalarExpression = binaryExpression.Left as ScalarExpression; if (scalarExpression != null) { SelectExpression selectCount = scalarExpression.Select as SelectExpression; if (selectCount != null && selectCount.Columns.Count == 1) { AggregateExpression aggregateExpression = (AggregateExpression)selectCount.Columns[0].Expression; if (aggregateExpression != null && aggregateExpression.AggregateName == "Count") { BinaryExpression where = selectCount.Where as BinaryExpression; if (where != null) { ColumnExpression columnExpression = where.Left as ColumnExpression; if (columnExpression != null) { TableAlias tableAlias = new TableAlias(); TableExpression tableExpression = (TableExpression)select.From; tableExpression = new TableExpression(tableAlias, tableExpression.Entity, tableExpression.Name); columnExpression = new ColumnExpression(columnExpression.Type, columnExpression.QueryType, tableAlias, columnExpression.Name); ColumnDeclaration columnDeclaration = new ColumnDeclaration(string.Empty, columnExpression, columnExpression.QueryType); BinaryExpression where2 = Expression.MakeBinary(where.NodeType, where.Left, columnExpression); selectCount = new SelectExpression(selectCount.Alias, selectCount.Columns, selectCount.From, where2); List <ColumnDeclaration> columns = new List <ColumnDeclaration> { new ColumnDeclaration("CountValue", new ScalarExpression(selectCount.Columns[0].Expression.Type, selectCount), selectCount.Columns[0].QueryType), columnDeclaration }; selectCount = new SelectExpression(tableAlias, columns.ToReadOnly(), tableExpression, null, selectCount.OrderBy, null, selectCount.IsDistinct, selectCount.Skip, selectCount.Take, selectCount.IsReverse); ColumnExpression countValueColumnExpression = new ColumnExpression(selectCount.Columns[0].Expression.Type, selectCount.Columns[0].QueryType, tableAlias, "CountValue"); SelectExpression newSelect = new SelectExpression(select.Alias, select.Columns, select.From, null, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take, select.IsReverse); JoinExpression joinExpression = new JoinExpression(JoinType.InnerJoin, newSelect, selectCount, Expression.MakeBinary(ExpressionType.Equal, columnExpression, where.Right)); select = new SelectExpression(newSelect.Alias, newSelect.Columns, joinExpression, Expression.MakeBinary(binaryExpression.NodeType, countValueColumnExpression, binaryExpression.Right), newSelect.OrderBy, newSelect.GroupBy, newSelect.IsDistinct, newSelect.Skip, newSelect.Take, newSelect.IsReverse); return(select); } } } } } } return(null); }
public Expression VisitTable(TableExpression expression) { TableVisited = true; return(expression); }
public bool SetConfig(DBSourceConfig dbSourceConfig) { this.FinishControl = true; this.LastControl = true; this.SelectStep = false; if (dbSourceConfig.ConnString == this.lastConnectionString) { return(true); } ClearAllSetting(); AvaliableConnecton = new OleDbConnection(dbSourceConfig.ConnString); Webb.Utilities.WaitingForm.SetWaitingMessage("Connecting database and reading data, Please wait.."); try { AvaliableConnecton.Open(); DataTable schemaTable = AvaliableConnecton.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); foreach (DataRow dr in schemaTable.Rows) { string tableName = dr["TABLE_NAME"].ToString(); TableExpression expresstion = new TableExpression(tableName); expresstion.IsExpression = false; this.checkedListTable.Items.Add(expresstion); } schemaTable.Dispose(); foreach (TableExpression expression in this.checkedListTable.Items) { schemaTable = AvaliableConnecton.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, expression.TableName, null }); expression.Fields.Clear(); foreach (DataRow dr in schemaTable.Rows) { string strName = dr["COLUMN_NAME"].ToString(); if (strName == null || strName == string.Empty) { continue; } if (!strName.StartsWith(expression.TableName + ".")) { strName = expression.TableName + "." + strName; } ColumnExpression column = new ColumnExpression(strName); expression.Fields.Add(column); } schemaTable.Dispose(); } lastConnectionString = dbSourceConfig.ConnString; return(true); } catch (System.Exception ex) { Webb.Utilities.MessageBoxEx.ShowError("Failed to connect datatbase.\n" + ex.Message); return(false); } }
private void IncludeCollection(IQuerySource querySource, Type resultType, Expression accessorLambda, INavigation navigation) { var selectExpression = QueryCompilationContext.FindSelectExpression(querySource); var primaryKeyProperties = navigation.EntityType.GetPrimaryKey().Properties; foreach (var property in primaryKeyProperties) { selectExpression .AddToOrderBy( QueryCompilationContext.GetColumnName(property), property, querySource, OrderingDirection.Asc); } var targetEntityType = navigation.GetTargetType(); var targetTableName = QueryCompilationContext.GetTableName(targetEntityType); var targetSelectExpression = new SelectExpression(); var targetTableAlias = CreateUniqueAlias(selectExpression, targetTableName.First().ToString().ToLower()); var targetTableExpression = new TableExpression( targetTableName, QueryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); foreach (var property in targetEntityType.Properties) { targetSelectExpression .AddToProjection( QueryCompilationContext.GetColumnName(property), property, querySource); } var innerJoinSelectExpression = selectExpression.Clone( ((ColumnExpression)selectExpression.OrderBy.First().Expression).TableAlias); innerJoinSelectExpression.IsDistinct = true; innerJoinSelectExpression.ClearProjection(); foreach (var columnExpression in innerJoinSelectExpression.OrderBy .Select(o => o.Expression) .Cast <ColumnExpression>()) { innerJoinSelectExpression.AddToProjection(columnExpression); } innerJoinSelectExpression.ClearOrderBy(); var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); targetSelectExpression.AddToOrderBy(selectExpression.OrderBy); innerJoinExpression.Predicate = BuildJoinEqualityExpression(navigation, primaryKeyProperties, targetTableExpression, innerJoinExpression); var readerParameter = Expression.Parameter(typeof(DbDataReader)); Expression = Expression.Call( QueryCompilationContext.QueryMethodProvider.IncludeCollectionMethod .MakeGenericMethod(resultType), QueryContextParameter, Expression, Expression.Constant(navigation), Expression.Call( QueryCompilationContext.QueryMethodProvider.QueryMethod .MakeGenericMethod(typeof(IValueReader)), QueryContextParameter, Expression.Constant(new CommandBuilder(targetSelectExpression, QueryCompilationContext)), Expression.Lambda( Expression.Call( _createValueReaderForIncludeMethodInfo, QueryContextParameter, readerParameter, Expression.Constant(targetEntityType)), readerParameter)), accessorLambda); }
public TableExpressionIdSet(TableExpression te) { TE = te; }
protected override Expression VisitTable(TableExpression tableExpression) { Sql.Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Name, tableExpression.Schema)); return(tableExpression); }
public object VisitTable(TableExpression tableExpression, SearchOptions context) { const string referenceSourceTableAlias = "refSource"; const string referenceTargetResourceTableAlias = "refTarget"; switch (tableExpression.Kind) { case TableExpressionKind.Normal: if (tableExpression.ChainLevel == 0) { StringBuilder.Append("SELECT ").Append(VLatest.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid1") .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table); } else { StringBuilder.Append("SELECT Sid1, ").Append(VLatest.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid2") .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table) .Append("INNER JOIN ").AppendLine(TableExpressionName(FindRestrictingPredecessorTableExpressionIndex())); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(VLatest.Resource.ResourceSurrogateId, null).Append(" = ").Append("Sid2"); } } using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); if (tableExpression.ChainLevel == 0) { // if chainLevel > 0, the intersection is already handled in the JOIN AppendIntersectionWithPredecessor(delimited, tableExpression); } if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } if (tableExpression.NormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.NormalizedPredicate.AcceptVisitor(tableExpression.SearchParameterQueryGenerator, GetContext()); } } break; case TableExpressionKind.Concatenation: StringBuilder.Append("SELECT * FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)); StringBuilder.AppendLine("UNION ALL"); goto case TableExpressionKind.Normal; case TableExpressionKind.All: StringBuilder.Append("SELECT ").Append(VLatest.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid1") .Append("FROM ").AppendLine(VLatest.Resource); using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); AppendDeletedClause(delimited); if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } } break; case TableExpressionKind.NotExists: StringBuilder.Append("SELECT Sid1 FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)); StringBuilder.AppendLine("WHERE Sid1 NOT IN").AppendLine("("); using (StringBuilder.Indent()) { StringBuilder.Append("SELECT ").AppendLine(VLatest.Resource.ResourceSurrogateId, null) .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table); using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } delimited.BeginDelimitedElement(); tableExpression.NormalizedPredicate.AcceptVisitor(tableExpression.SearchParameterQueryGenerator, GetContext()); } } StringBuilder.AppendLine(")"); break; case TableExpressionKind.Top: var(paramInfo, sortOrder) = context.GetFirstSupportedSortParam(); var tableExpressionName = TableExpressionName(_tableExpressionCounter - 1); var sortExpression = (paramInfo == null || paramInfo.Name == KnownQueryParameterNames.LastUpdated) ? null : $"{tableExpressionName}.SortValue"; // Everything in the top expression is considered a match StringBuilder.Append("SELECT DISTINCT TOP (").Append(Parameters.AddParameter(context.MaxItemCount + 1)).Append(") Sid1, 1 AS IsMatch, 0 AS IsPartial ") .AppendLine(sortExpression == null ? string.Empty : $", {sortExpression}") .Append("FROM ").AppendLine(tableExpressionName) .AppendLine($"ORDER BY {(sortExpression == null ? string.Empty : $"{sortExpression} {(sortOrder == SortOrder.Ascending ? "ASC" : "DESC")}, ")} Sid1 {((sortExpression != null || sortOrder == SortOrder.Ascending) ? "ASC" : "DESC")}"); // For any includes, the source of the resource surrogate ids to join on is saved _cteMainSelect = TableExpressionName(_tableExpressionCounter); break;
private static IEnumerable <ColumnAssignment> GetAssignmentsForPrimaryKeys(ISyntaxProvider syntax, TableExpression table, ParameterExpression parExp, IEntity entity) { var entityType = parExp != null ? parExp.Type : entity.EntityType; var assignments = new List <ColumnAssignment>(); foreach (var p in PropertyUnity.GetPrimaryProperties(entityType)) { var pvExp = GetPrimaryValueExpression(syntax, table, parExp, entity, p); if (pvExp != null) { var columnExp = (ColumnExpression)GetMemberExpression(table, p); assignments.Add(new ColumnAssignment(columnExp, pvExp)); } } return(assignments); }
private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories( IQuerySource querySource, IEnumerable <INavigation> navigationPath) { var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var targetTableExpression = selectExpression.GetTableForQuerySource(querySource); var canProduceInnerJoin = true; var navigationCount = 0; foreach (var navigation in navigationPath) { var queryIndex = _queryIndexes[navigationCount]; navigationCount++; var targetEntityType = navigation.GetTargetType(); var targetTableName = _relationalAnnotationProvider.For(targetEntityType).TableName; var targetTableAlias = targetTableName[0].ToString().ToLower(); if (!navigation.IsCollection()) { var joinedTableExpression = new TableExpression( targetTableName, _relationalAnnotationProvider.For(targetEntityType).Schema, targetTableAlias, querySource); var valueBufferOffset = selectExpression.Projection.Count; canProduceInnerJoin = canProduceInnerJoin && navigation.ForeignKey.IsRequired && navigation.IsDependentToPrincipal(); var joinExpression = canProduceInnerJoin ? selectExpression .AddInnerJoin(joinedTableExpression) : selectExpression .AddOuterJoin(joinedTableExpression); var oldPredicate = selectExpression.Predicate; var materializer = _materializerFactory .CreateMaterializer( targetEntityType, selectExpression, (p, se) => se.AddToProjection( new AliasExpression( new ColumnExpression( _relationalAnnotationProvider.For(p).ColumnName, p, joinedTableExpression))) - valueBufferOffset, querySource: null); if (selectExpression.Predicate != oldPredicate) { var newJoinExpression = AdjustJoinExpression(selectExpression, joinExpression); selectExpression.Predicate = oldPredicate; selectExpression.RemoveTable(joinExpression); selectExpression.AddTable(newJoinExpression); joinExpression = newJoinExpression; } joinExpression.Predicate = BuildJoinEqualityExpression( navigation, navigation.IsDependentToPrincipal() ? targetTableExpression : joinExpression, navigation.IsDependentToPrincipal() ? joinExpression : targetTableExpression, querySource); targetTableExpression = joinedTableExpression; yield return (Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateReferenceIncludeRelatedValuesStrategyMethod, Expression.Convert( EntityQueryModelVisitor.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(valueBufferOffset), Expression.Constant(queryIndex), materializer))); } else { var principalTable = (selectExpression.Tables.Count == 1) && selectExpression.Tables.OfType <SelectExpression>().Any(s => s.Tables.Any(t => t.QuerySource == querySource)) // true when select is wrapped e.g. when RowNumber paging is enabled ? selectExpression.Tables[0] : selectExpression.Tables.Last(t => t.QuerySource == querySource); foreach (var property in navigation.ForeignKey.PrincipalKey.Properties) { selectExpression .AddToOrderBy( _relationalAnnotationProvider.For(property).ColumnName, property, principalTable, OrderingDirection.Asc); } var targetSelectExpression = _selectExpressionFactory.Create(); targetTableExpression = new TableExpression( targetTableName, _relationalAnnotationProvider.For(targetEntityType).Schema, targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); var materializer = _materializerFactory .CreateMaterializer( targetEntityType, targetSelectExpression, (p, se) => se.AddToProjection( _relationalAnnotationProvider.For(p).ColumnName, p, querySource), querySource: null); var innerJoinSelectExpression = selectExpression.Clone( selectExpression.OrderBy .Select(o => o.Expression) .Last(o => o.IsAliasWithColumnExpression()) .TryGetColumnExpression().TableAlias); innerJoinSelectExpression.ClearProjection(); var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); LiftOrderBy(innerJoinSelectExpression, targetSelectExpression, innerJoinExpression); innerJoinSelectExpression.IsDistinct = true; innerJoinExpression.Predicate = BuildJoinEqualityExpression( navigation, targetTableExpression, innerJoinExpression, querySource); selectExpression = targetSelectExpression; yield return (Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateCollectionIncludeRelatedValuesStrategyMethod, Expression.Call( _queryCompilationContext.QueryMethodProvider.QueryMethod, EntityQueryModelVisitor.QueryContextParameter, Expression.Constant( _shaperCommandContextFactory.Create( () => _querySqlGeneratorFactory .CreateDefault(targetSelectExpression))), Expression.Constant(queryIndex, typeof(int?))), materializer))); } } }
protected DeleteCommand UpdateDelete(DeleteCommand delete, TableExpression table, Expression where) { if (table != delete.Table || where != delete.Where) { return new DeleteCommand(table, where,delete.Instance, delete.SupportsVersionCheck); } return delete; }
protected override Expression VisitTable(TableExpression table) { if (gatheredKeys != null) gatheredKeys.Add(table.GetIdExpression()); return table; }
public virtual string GetColumnName(TableExpression tableExpression, MemberInfo memberInfo, DataContext dataContext) { return(GetColumnName(tableExpression.Type, memberInfo, dataContext)); }
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); }
public object VisitTable(TableExpression tableExpression, SearchOptions context) { string referenceTableAlias = "ref"; string resourceTableAlias = "r"; switch (tableExpression.Kind) { case TableExpressionKind.Normal: if (tableExpression.ChainLevel == 0) { StringBuilder.Append("SELECT ").Append(VLatest.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid1") .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table); } else { StringBuilder.Append("SELECT Sid1, ").Append(VLatest.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid2") .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table) .Append("INNER JOIN ").AppendLine(TableExpressionName(FindRestrictingPredecessorTableExpressionIndex())); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(VLatest.Resource.ResourceSurrogateId, null).Append(" = ").Append("Sid2"); } } using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); if (tableExpression.ChainLevel == 0) { // if chainLevel > 0, the intersection is already handled in the JOIN AppendIntersectionWithPredecessor(delimited, tableExpression); } if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } if (tableExpression.NormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.NormalizedPredicate.AcceptVisitor(tableExpression.SearchParameterQueryGenerator, GetContext()); } } break; case TableExpressionKind.Concatenation: StringBuilder.Append("SELECT * FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)); StringBuilder.AppendLine("UNION ALL"); goto case TableExpressionKind.Normal; case TableExpressionKind.All: StringBuilder.Append("SELECT ").Append(VLatest.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid1") .Append("FROM ").AppendLine(VLatest.Resource); using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); AppendDeletedClause(delimited); if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } } break; case TableExpressionKind.NotExists: StringBuilder.Append("SELECT Sid1 FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)); StringBuilder.AppendLine("WHERE Sid1 NOT IN").AppendLine("("); using (StringBuilder.Indent()) { StringBuilder.Append("SELECT ").AppendLine(VLatest.Resource.ResourceSurrogateId, null) .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table); using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } delimited.BeginDelimitedElement(); tableExpression.NormalizedPredicate.AcceptVisitor(tableExpression.SearchParameterQueryGenerator, GetContext()); } } StringBuilder.AppendLine(")"); break; case TableExpressionKind.Top: // Everything in the top expression is considered a match StringBuilder.Append("SELECT DISTINCT TOP (").Append(Parameters.AddParameter(context.MaxItemCount + 1)).AppendLine(") Sid1, 1 AS IsMatch ") .Append("FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)) .AppendLine("ORDER BY Sid1 ASC"); // For any includes, the source of the resource surrogate ids to join on is saved _cteMainSelect = TableExpressionName(_tableExpressionCounter); break; case TableExpressionKind.Chain: var chainedExpression = (ChainedExpression)tableExpression.NormalizedPredicate; string resourceTableAlias2 = "r2"; StringBuilder.Append("SELECT "); if (tableExpression.ChainLevel == 1) { StringBuilder.Append(VLatest.ReferenceSearchParam.ResourceSurrogateId, referenceTableAlias).Append(" AS ").Append(chainedExpression.Reversed ? "Sid2" : "Sid1").Append(", "); } else { StringBuilder.Append("Sid1, "); } StringBuilder.Append(VLatest.Resource.ResourceSurrogateId, chainedExpression.Reversed && tableExpression.ChainLevel > 1 ? referenceTableAlias : resourceTableAlias).Append(" AS ").AppendLine(chainedExpression.Reversed && tableExpression.ChainLevel == 1 ? "Sid1 " : "Sid2 ") .Append("FROM ").Append(VLatest.ReferenceSearchParam).Append(' ').AppendLine(referenceTableAlias) .Append("INNER JOIN ").Append(VLatest.Resource).Append(' ').AppendLine(resourceTableAlias); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ReferenceResourceTypeId, referenceTableAlias) .Append(" = ").Append(VLatest.Resource.ResourceTypeId, resourceTableAlias); delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ReferenceResourceId, referenceTableAlias) .Append(" = ").Append(VLatest.Resource.ResourceId, resourceTableAlias); } // Denormalized predicates on reverse chains need to be applied via a join to the resource table if (tableExpression.DenormalizedPredicate != null && chainedExpression.Reversed) { StringBuilder.Append("INNER JOIN ").Append(VLatest.Resource).Append(' ').AppendLine(resourceTableAlias2); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ResourceSurrogateId, referenceTableAlias) .Append(" = ").Append(VLatest.Resource.ResourceSurrogateId, resourceTableAlias2); delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext(resourceTableAlias2)); } } if (tableExpression.ChainLevel > 1) { StringBuilder.Append("INNER JOIN ").AppendLine(TableExpressionName(FindRestrictingPredecessorTableExpressionIndex())); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(VLatest.Resource.ResourceSurrogateId, chainedExpression.Reversed ? resourceTableAlias : referenceTableAlias).Append(" = ").Append("Sid2"); } } using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.SearchParamId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(VLatest.ReferenceSearchParam.SearchParamId, Model.GetSearchParamId(chainedExpression.ReferenceSearchParameter.Url))); AppendHistoryClause(delimited, resourceTableAlias); AppendHistoryClause(delimited, referenceTableAlias); delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ResourceTypeId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(VLatest.ReferenceSearchParam.ResourceTypeId, Model.GetResourceTypeId(chainedExpression.ResourceType))); delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ReferenceResourceTypeId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(VLatest.ReferenceSearchParam.ReferenceResourceTypeId, Model.GetResourceTypeId(chainedExpression.TargetResourceType))); if (tableExpression.ChainLevel == 1) { // if > 1, the intersection is handled by the JOIN AppendIntersectionWithPredecessor(delimited, tableExpression, chainedExpression.Reversed ? resourceTableAlias : referenceTableAlias); } if (tableExpression.DenormalizedPredicate != null && !chainedExpression.Reversed) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext(resourceTableAlias)); } } break; case TableExpressionKind.Include: var includeExpression = (IncludeExpression)tableExpression.NormalizedPredicate; StringBuilder.Append("SELECT DISTINCT "); StringBuilder.Append(VLatest.Resource.ResourceSurrogateId, resourceTableAlias).AppendLine(" AS Sid1, 0 AS IsMatch") .Append("FROM ").Append(VLatest.ReferenceSearchParam).Append(' ').AppendLine(referenceTableAlias) .Append("INNER JOIN ").Append(VLatest.Resource).Append(' ').AppendLine(resourceTableAlias); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ReferenceResourceTypeId, referenceTableAlias) .Append(" = ").Append(VLatest.Resource.ResourceTypeId, resourceTableAlias); delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ReferenceResourceId, referenceTableAlias) .Append(" = ").Append(VLatest.Resource.ResourceId, resourceTableAlias); } using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { if (!includeExpression.WildCard) { delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.SearchParamId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(VLatest.ReferenceSearchParam.SearchParamId, Model.GetSearchParamId(includeExpression.ReferenceSearchParameter.Url))); if (includeExpression.TargetResourceType != null) { delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ReferenceResourceTypeId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(VLatest.ReferenceSearchParam.ReferenceResourceTypeId, Model.GetResourceTypeId(includeExpression.TargetResourceType))); } } AppendHistoryClause(delimited, resourceTableAlias); AppendHistoryClause(delimited, referenceTableAlias); delimited.BeginDelimitedElement().Append(VLatest.ReferenceSearchParam.ResourceTypeId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(VLatest.ReferenceSearchParam.ResourceTypeId, Model.GetResourceTypeId(includeExpression.ResourceType))); // Limit the join to the main select CTE. // The main select will have max+1 items in the result set to account for paging, so we only want to join using the max amount. delimited.BeginDelimitedElement().Append(VLatest.Resource.ResourceSurrogateId, referenceTableAlias) .Append(" IN (SELECT TOP(") .Append(Parameters.AddParameter(context.MaxItemCount)) .Append(") Sid1 FROM ").Append(_cteMainSelect).Append(")"); } if (_includeCtes == null) { _includeCtes = new List <string>(); } _includeCtes.Add(TableExpressionName(_tableExpressionCounter)); break; case TableExpressionKind.IncludeUnionAll: StringBuilder.AppendLine("SELECT Sid1, IsMatch"); StringBuilder.Append("FROM ").AppendLine(_cteMainSelect); foreach (var includeCte in _includeCtes) { StringBuilder.AppendLine("UNION ALL"); StringBuilder.AppendLine("SELECT Sid1, IsMatch "); StringBuilder.Append("FROM ").AppendLine(includeCte); } break; default: throw new ArgumentOutOfRangeException(tableExpression.Kind.ToString()); } return(null); }
protected virtual bool CompareTable(TableExpression a, TableExpression b) { return a.Name == b.Name; }
public JoinExpressionViewModel(HermesViewModel parent, TableExpression model) : base(parent, model) { //this.Filter = new BooleanExpressionViewModel(this, "ON"); }
protected internal override Expression VisitTable(TableExpression table) { this.aliases.Add(table.Alias); return base.VisitTable(table); }
protected override Expression VisitTable(TableExpression tableExpression) => tableExpression;
// make a variable declaration / initialization for dependent generated values private CommandExpression GetDependentGeneratedVariableDeclaration(MappingEntity entity, MappingTable table, List<MemberInfo> members, Expression instance, Dictionary<MemberInfo, Expression> map) { // first make command that retrieves the generated ids if any DeclarationCommand genIdCommand = null; var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList(); if (generatedIds.Count > 0) { genIdCommand = this.GetGeneratedIdCommand(entity, members, map); // if that's all there is then just return the generated ids if (members.Count == generatedIds.Count) { return genIdCommand; } } // next make command that retrieves the generated members // only consider members that were not generated ids members = members.Except(generatedIds).ToList(); var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table)); Expression where = null; if (generatedIds.Count > 0) { where = generatedIds.Select((m, i) => this.GetMemberExpression(tex, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = this.GetIdentityCheck(tex, entity, instance); } TableAlias selectAlias = new TableAlias(); var columns = new List<ColumnDeclaration>(); var variables = new List<VariableDeclaration>(); foreach (var mi in members) { ColumnExpression col = (ColumnExpression)this.GetMemberExpression(tex, entity, mi); columns.Add(new ColumnDeclaration(this.mapping.GetColumnName(entity, mi), col, col.QueryType)); ColumnExpression vcol = new ColumnExpression(col.Type, col.QueryType, selectAlias, col.Name); variables.Add(new VariableDeclaration(mi.Name, col.QueryType, vcol)); map.Add(mi, new VariableExpression(mi.Name, col.Type, col.QueryType)); } var genMembersCommand = new DeclarationCommand(variables, new SelectExpression(selectAlias, columns, tex, where)); if (genIdCommand != null) { return new BlockCommand(genIdCommand, genMembersCommand); } return genMembersCommand; }
/// <summary> /// Format a table expression /// </summary> /// <param name="tableExpression">the table expression to be formatted</param> /// <returns>table expression unchanged</returns> protected override Expression VisitTable(TableExpression tableExpression) { this.Builder.Append(tableExpression.Name); return(tableExpression); }
protected override Expression VisitTable(TableExpression table) { TableAlias newAlias = new TableAlias(); this.map[table.Alias] = newAlias; return new TableExpression(newAlias, table.Entity, table.Name); }
public static Expression Replace(Expression where, Expression expression, TableExpression table, IEnumerable <ColumnDeclaration> columns) { var visitor = new PolicyConditionReplacer { where = where, columns = columns }; visitor.Visit(PartialEvaluator.Eval(expression)); return(visitor.where); }
/// <summary> /// 返回插入具体实体时的 <see cref="ColumnAssignment"/> 集合。 /// </summary> /// <param name="syntax"></param> /// <param name="table"></param> /// <param name="parExp"></param> /// <returns></returns> private static IEnumerable <ColumnAssignment> GetInsertArguments(ISyntaxProvider syntax, TableExpression table, ParameterExpression parExp) { IEnumerable <IProperty> properties = null; List <string> modifiedNames = null; if ((modifiedNames = GetReferenceModifiedProperties()) != null) { properties = GetModifiedProperties(table.Type, modifiedNames); } var assignments = properties .Select(m => new ColumnAssignment( (ColumnExpression)GetMemberExpression(table, m), Expression.MakeMemberAccess(parExp, m.Info.ReflectionInfo) )).ToList(); assignments.AddRange(GetAssignmentsForPrimaryKeys(syntax, table, parExp, null)); return(assignments); }
public Expression VisitTable(TableExpression tableExpression, object context) { throw new InvalidOperationException(); }
/// <summary> /// Registers an association /// </summary> /// <param name="tableExpression">The table holding the member, to become the joinedTable</param> /// <param name="tableMemberInfo"></param> /// <param name="otherType"></param> /// <param name="builderContext"></param> /// <returns></returns> public virtual TableExpression RegisterAssociation(TableExpression tableExpression, MemberInfo tableMemberInfo, Type otherType, BuilderContext builderContext) { IList <MemberInfo> otherKeys; TableJoinType joinType; string joinID; var theseKeys = DataMapper.GetAssociation(tableExpression, tableMemberInfo, otherType, out otherKeys, out joinType, out joinID, builderContext.QueryContext.DataContext); // if the memberInfo has no corresponding association, we get a null, that we propagate if (theseKeys == null) { return(null); } // the current table has the foreign key, the other table the referenced (usually primary) key if (theseKeys.Count != otherKeys.Count) { throw Error.BadArgument("S0128: Association arguments (FK and ref'd PK) don't match"); } // we first create the table, with the JoinID, and we MUST complete the table later, with the Join() method var otherTableExpression = new TableExpression(otherType, DataMapper.GetTableName(otherType, builderContext.QueryContext.DataContext), joinID); Expression joinExpression = null; var createdColumns = new List <ColumnExpression>(); for (int keyIndex = 0; keyIndex < theseKeys.Count; keyIndex++) { // joinedKey is registered, even if unused by final select (required columns will be filtered anyway) Expression otherKey = RegisterColumn(otherTableExpression, otherKeys[keyIndex], builderContext); // foreign is created, we will store it later if this assocation is registered too Expression thisKey = CreateColumn(tableExpression, theseKeys[keyIndex], builderContext); createdColumns.Add((ColumnExpression)thisKey); // if the key is nullable, then convert it // TODO: this will probably need to be changed if (otherKey.Type.IsNullable()) { otherKey = Expression.Convert(otherKey, otherKey.Type.GetNullableType()); } if (thisKey.Type.IsNullable()) { thisKey = Expression.Convert(thisKey, thisKey.Type.GetNullableType()); } // the other key is set as left operand, this must be this way // since some vendors (SQL Server) don't support the opposite var referenceExpression = Expression.Equal(otherKey, thisKey); // if we already have a join expression, then we have a double condition here, so "AND" it if (joinExpression != null) { joinExpression = Expression.And(joinExpression, referenceExpression); } else { joinExpression = referenceExpression; } } // we complete the table here, now that we have all join information otherTableExpression.Join(joinType, tableExpression, joinExpression); // our table is created, with the expressions // now check if we didn't register exactly the same var existingTable = (from t in builderContext.EnumerateScopeTables() where t.IsEqualTo(otherTableExpression) select t).SingleOrDefault(); if (existingTable != null) { return(existingTable); } builderContext.CurrentSelect.Tables.Add(otherTableExpression); foreach (var createdColumn in createdColumns) { builderContext.CurrentSelect.Columns.Add(createdColumn); } return(otherTableExpression); }
public BinaryExpression ToEqualExpression(object obj, TableExpression table = null) { var value = GetValue(obj); return(Expression.MakeBinary(ExpressionType.Equal, ToColumnExpression(table), Expression.Constant(value))); }
private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories( IQuerySource querySource, IEnumerable <INavigation> navigationPath) { var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var targetTableExpression = selectExpression.FindTableForQuerySource(querySource); var readerIndex = 0; var canProduceInnerJoin = true; foreach (var navigation in navigationPath) { var targetEntityType = navigation.GetTargetType(); var targetTableName = _queryCompilationContext.GetTableName(targetEntityType); var targetTableAlias = targetTableName[0].ToString().ToLower(); if (!navigation.IsCollection()) { var joinedTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); var valueBufferOffset = selectExpression.Projection.Count; canProduceInnerJoin = canProduceInnerJoin && (navigation.ForeignKey.IsRequired && navigation.PointsToPrincipal()); var joinExpression = canProduceInnerJoin ? selectExpression .AddInnerJoin(joinedTableExpression) : selectExpression .AddOuterJoin(joinedTableExpression); var materializer = new MaterializerFactory( _queryCompilationContext.EntityMaterializerSource) .CreateMaterializer( targetEntityType, selectExpression, projectionAdder: (p, se) => se.AddToProjection( new AliasExpression( new ColumnExpression( _queryCompilationContext.GetColumnName(p), p, joinedTableExpression))) - valueBufferOffset, querySource: null); joinExpression.Predicate = BuildJoinEqualityExpression( navigation, (navigation.PointsToPrincipal() ? targetEntityType : navigation.EntityType) .GetPrimaryKey().Properties, navigation.PointsToPrincipal() ? targetTableExpression : joinExpression, navigation.PointsToPrincipal() ? joinExpression : targetTableExpression); targetTableExpression = joinedTableExpression; yield return (Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateReferenceIncludeRelatedValuesStrategyMethod, Expression.Convert( EntityQueryModelVisitor.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(valueBufferOffset), Expression.Constant(readerIndex), materializer))); } else { var principalTable = selectExpression.Tables.Last(t => t.QuerySource == querySource); foreach (var property in navigation.EntityType.GetPrimaryKey().Properties) { selectExpression .AddToOrderBy( _queryCompilationContext.GetColumnName(property), property, principalTable, OrderingDirection.Asc); } var targetSelectExpression = new SelectExpression(); targetTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); var materializer = new MaterializerFactory( _queryCompilationContext.EntityMaterializerSource) .CreateMaterializer( targetEntityType, targetSelectExpression, (p, se) => se.AddToProjection( _queryCompilationContext.GetColumnName(p), p, querySource), querySource: null); var innerJoinSelectExpression = selectExpression.Clone( selectExpression.OrderBy.Select(o => o.Expression).Last(o => o.IsAliasWithColumnExpression()) .TryGetColumnExpression().TableAlias); innerJoinSelectExpression.IsDistinct = true; innerJoinSelectExpression.ClearProjection(); foreach (var expression in innerJoinSelectExpression.OrderBy .Select(o => o.Expression)) { innerJoinSelectExpression.AddToProjection(expression); } innerJoinSelectExpression.ClearOrderBy(); var primaryKeyProperties = navigation.EntityType.GetPrimaryKey().Properties; var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); targetSelectExpression.UpdateOrderByColumnBinding(selectExpression.OrderBy, innerJoinExpression); innerJoinExpression.Predicate = BuildJoinEqualityExpression( navigation, primaryKeyProperties, targetTableExpression, innerJoinExpression); selectExpression = targetSelectExpression; readerIndex++; yield return (Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateCollectionIncludeRelatedValuesStrategyMethod, Expression.Call( _queryCompilationContext.QueryMethodProvider.QueryMethod, EntityQueryModelVisitor.QueryContextParameter, Expression.Constant( new CommandBuilder( () => _queryCompilationContext.CreateSqlQueryGenerator(targetSelectExpression), _queryCompilationContext.ValueBufferFactoryFactory))), materializer))); } } }
public virtual Expression GetDeleteExpression(IEntityMapping mapping, Expression instance, LambdaExpression deleteCheck) { TableExpression table = new TableExpression(new TableAlias(), mapping); Expression where = null; if (instance != null) where = this.GetIdentityCheck(table, mapping, instance); if (deleteCheck != null) { Expression row = this.GetEntityExpression(table, mapping); Expression pred = DbExpressionReplacer.Replace(deleteCheck.Body, deleteCheck.Parameters[0], row); where = (where != null) ? where.And(pred) : pred; } bool supportsVersionCheck = false; if (mapping.Version != null && instance != null) { //var versionValue = GetVersionValue(entity, instance); //var versionCheck = GetMemberExpression(table, entity, entity.Version).Equal(Expression.Constant(versionValue)); //where = (where != null) ? where.And(versionCheck) : versionCheck; var version = mapping.Version; var versionValue = GetVersionValue(mapping, instance); var versionExp = Expression.Constant(versionValue, version.MemberType); var memberExpression = GetMemberExpression(table, mapping, mapping.Version); if (version.MemberType.IsNullable()) { var versionCheck = versionValue == null ? (Expression)memberExpression.Equal(Expression.Constant(null, version.MemberType)) : memberExpression.Equal(versionExp); where = (where != null) ? where.And(versionCheck) : versionCheck; } else { var versionCheck = memberExpression.Equal(versionExp); where = (where != null) ? where.And(versionCheck) : versionCheck; } supportsVersionCheck = true; } object o = null; var c = instance as ConstantExpression; if (c != null) o = c.Value; return new DeleteCommand(table, where, o, supportsVersionCheck); }
protected override Expression VisitTable(TableExpression table) { this.aliases.Add(table.Alias); return(table); }
public virtual Expression GetInsertExpression(IEntityMapping mapping, Expression instance, LambdaExpression selector) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, mapping); var assignments = this.GetInsertColumnAssignments(table, instance, mapping, m => !m.IsGenerated && !m.IsVersion).ToArray(); object o = null; var c = instance as ConstantExpression; if (c != null) o = c.Value; if (selector != null) { return new BlockCommand( new InsertCommand(table, assignments, o), this.GetInsertResult(mapping, instance, selector, null) ); } return new InsertCommand(table, assignments, o); }
private GroupByExpression(TableExpression tableExpression) : base(ExpressionType, tableExpression) { Table = tableExpression; }
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); }
/// <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 virtual Expression GetUpdateExpression(IEntityMapping mapping, Expression instance, LambdaExpression updateCheck, LambdaExpression selector, Expression @else) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, mapping); var where = this.GetIdentityCheck(table, mapping, instance); if (updateCheck != null) { Expression typeProjector = this.GetEntityExpression(table, mapping); Expression pred = DbExpressionReplacer.Replace(updateCheck.Body, updateCheck.Parameters[0], typeProjector); where = where != null ? where.And(pred) : pred; } var assignments = this.GetColumnAssignments(table, instance, mapping, m => m.IsUpdatable && !m.IsVersion); var version = mapping.Version; bool supportsVersionCheck = false; if (version != null) { var versionValue = GetVersionValue(mapping, instance); var versionExp = Expression.Constant(versionValue, version.MemberType); var memberExpression = GetMemberExpression(table, mapping, mapping.Version); var versionCheck = memberExpression.Equal(versionExp); where = (where != null) ? where.And(versionCheck) : versionCheck; if (version.MemberType.IsNullable()) { var versionAssignment = new ColumnAssignment( memberExpression as ColumnExpression, versionValue == null ? (Expression)Expression.Constant(1, version.MemberType) : Expression.Add(memberExpression, Expression.Constant(1, version.MemberType)) ); assignments.Add(versionAssignment); supportsVersionCheck = true; } else { var versionAssignment = new ColumnAssignment( memberExpression as ColumnExpression, Expression.Add(memberExpression, Expression.Constant(1, version.MemberType)) ); assignments.Add(versionAssignment); supportsVersionCheck = true; } } object o = null; var c = instance as ConstantExpression; if (c != null) o = c.Value; Expression update = new UpdateCommand(table, where, o, supportsVersionCheck, assignments); if (selector != null) { return new BlockCommand( update, new IFCommand( this.GetRowsAffectedExpression(update).GreaterThan(Expression.Constant(0)), this.GetUpdateResult(mapping, instance, selector), @else ) ); } else if (@else != null) { return new BlockCommand( update, new IFCommand( this.GetRowsAffectedExpression(update).LessThanOrEqual(Expression.Constant(0)), @else, null ) ); } else { return update; } }
public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var assignments = this.GetColumnAssignments(table, instance, entity, (e, m) => !this.mapping.IsGenerated(e, m)); if (selector != null) { return new BlockCommand( new InsertCommand(table, assignments), this.GetInsertResult(entity, instance, selector, null) ); } return new InsertCommand(table, assignments); }
protected abstract Expression VisitTable([NotNull] TableExpression tableExpression);
public override Expression GetUpdateExpression(MappingEntity entity, Expression instance, LambdaExpression updateCheck, LambdaExpression selector, Expression @else) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var where = this.GetIdentityCheck(table, entity, instance); if (updateCheck != null) { Expression typeProjector = this.GetEntityExpression(table, entity); Expression pred = DbExpressionReplacer.Replace(updateCheck.Body, updateCheck.Parameters[0], typeProjector); where = where.And(pred); } var assignments = this.GetColumnAssignments(table, instance, entity, (e, m) => this.mapping.IsUpdatable(e, m)); Expression update = new UpdateCommand(table, where, assignments); if (selector != null) { return new BlockCommand( update, new IFCommand( this.translator.Linguist.Language.GetRowsAffectedExpression(update).GreaterThan(Expression.Constant(0)), this.GetUpdateResult(entity, instance, selector), @else ) ); } else if (@else != null) { return new BlockCommand( update, new IFCommand( this.translator.Linguist.Language.GetRowsAffectedExpression(update).LessThanOrEqual(Expression.Constant(0)), @else, null ) ); } else { return update; } }
protected override Expression VisitTable(TableExpression tableExpression) { Check.NotNull(tableExpression, nameof(tableExpression)); return(tableExpression); }
protected virtual Expression VisitTable(TableExpression table) { return table; }
/// <summary> /// Visits the table. /// </summary> /// <param name="tableExpression">The table expression.</param> /// <returns> /// Expression /// </returns> public virtual Expression VisitTable(TableExpression tableExpression) { _sqlBuilder.AppendFormat(" {0} {1}", TableExpression.FromStatement, tableExpression.TablePart); return(tableExpression); }
private static IEnumerable<ColumnExpression> KeysTable(TableExpression table) { yield return new ColumnExpression(typeof(int), table.Alias, SqlBuilder.PrimaryKeyName) ; }
public object VisitTable(TableExpression tableExpression, SearchOptions context) { switch (tableExpression.Kind) { case TableExpressionKind.Normal: if (tableExpression.ChainLevel == 0) { StringBuilder.Append("SELECT ").Append(V1.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid1") .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table); } else { StringBuilder.Append("SELECT Sid1, ").Append(V1.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid2") .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table) .Append("INNER JOIN ").AppendLine(TableExpressionName(FindRestrictingPredecessorTableExpressionIndex())); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(V1.Resource.ResourceSurrogateId, null).Append(" = ").Append("Sid2"); } } using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); if (tableExpression.ChainLevel == 0) { // if chainLevel > 0, the intersection is already handled in the JOIN AppendIntersectionWithPredecessor(delimited, tableExpression); } if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } if (tableExpression.NormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.NormalizedPredicate.AcceptVisitor(tableExpression.SearchParameterQueryGenerator, GetContext()); } } break; case TableExpressionKind.Concatenation: StringBuilder.Append("SELECT * FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)); StringBuilder.AppendLine("UNION ALL"); goto case TableExpressionKind.Normal; case TableExpressionKind.All: StringBuilder.Append("SELECT ").Append(V1.Resource.ResourceSurrogateId, null).AppendLine(" AS Sid1") .Append("FROM ").AppendLine(V1.Resource); using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); AppendDeletedClause(delimited); if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } } break; case TableExpressionKind.NotExists: StringBuilder.Append("SELECT Sid1 FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)); StringBuilder.AppendLine("WHERE Sid1 NOT IN").AppendLine("("); using (StringBuilder.Indent()) { StringBuilder.Append("SELECT ").AppendLine(V1.Resource.ResourceSurrogateId, null) .Append("FROM ").AppendLine(tableExpression.SearchParameterQueryGenerator.Table); using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { AppendHistoryClause(delimited); if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext()); } delimited.BeginDelimitedElement(); tableExpression.NormalizedPredicate.AcceptVisitor(tableExpression.SearchParameterQueryGenerator, GetContext()); } } StringBuilder.AppendLine(")"); break; case TableExpressionKind.Top: StringBuilder.Append("SELECT DISTINCT TOP (").Append(Parameters.AddParameter(context.MaxItemCount + 1)).AppendLine(") Sid1 ") .Append("FROM ").AppendLine(TableExpressionName(_tableExpressionCounter - 1)) .AppendLine("ORDER BY Sid1 ASC"); break; case TableExpressionKind.Chain: var chainedExpression = (ChainedExpression)tableExpression.NormalizedPredicate; string referenceTableAlias = "ref"; string resourceTableAlias = "r"; StringBuilder.Append("SELECT "); if (tableExpression.ChainLevel == 1) { StringBuilder.Append(V1.ReferenceSearchParam.ResourceSurrogateId, referenceTableAlias).Append(" AS Sid1, "); } else { StringBuilder.Append("Sid1, "); } StringBuilder.Append(V1.Resource.ResourceSurrogateId, resourceTableAlias).AppendLine(" AS Sid2") .Append("FROM ").Append(V1.ReferenceSearchParam).Append(' ').AppendLine(referenceTableAlias) .Append("INNER JOIN ").Append(V1.Resource).Append(' ').AppendLine(resourceTableAlias); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(V1.ReferenceSearchParam.ReferenceResourceTypeId, referenceTableAlias) .Append(" = ").Append(V1.Resource.ResourceTypeId, resourceTableAlias); delimited.BeginDelimitedElement().Append(V1.ReferenceSearchParam.ReferenceResourceId, referenceTableAlias) .Append(" = ").Append(V1.Resource.ResourceId, resourceTableAlias); } if (tableExpression.ChainLevel > 1) { StringBuilder.Append("INNER JOIN ").AppendLine(TableExpressionName(FindRestrictingPredecessorTableExpressionIndex())); using (var delimited = StringBuilder.BeginDelimitedOnClause()) { delimited.BeginDelimitedElement().Append(V1.Resource.ResourceSurrogateId, referenceTableAlias).Append(" = ").Append("Sid2"); } } using (var delimited = StringBuilder.BeginDelimitedWhereClause()) { delimited.BeginDelimitedElement().Append(V1.ReferenceSearchParam.SearchParamId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(V1.ReferenceSearchParam.SearchParamId, Model.GetSearchParamId(chainedExpression.ReferenceSearchParameter.Url))); AppendHistoryClause(delimited, resourceTableAlias); AppendHistoryClause(delimited, referenceTableAlias); delimited.BeginDelimitedElement().Append(V1.ReferenceSearchParam.ResourceTypeId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(V1.ReferenceSearchParam.ResourceTypeId, Model.GetResourceTypeId(chainedExpression.ResourceType))); delimited.BeginDelimitedElement().Append(V1.ReferenceSearchParam.ReferenceResourceTypeId, referenceTableAlias) .Append(" = ").Append(Parameters.AddParameter(V1.ReferenceSearchParam.ReferenceResourceTypeId, Model.GetResourceTypeId(chainedExpression.TargetResourceType))); if (tableExpression.ChainLevel == 1) { // if > 1, the intersection is handled by the JOIN AppendIntersectionWithPredecessor(delimited, tableExpression, referenceTableAlias); } if (tableExpression.DenormalizedPredicate != null) { delimited.BeginDelimitedElement(); tableExpression.DenormalizedPredicate?.AcceptVisitor(DispatchingDenormalizedSearchParameterQueryGenerator.Instance, GetContext(resourceTableAlias)); } } break; default: throw new ArgumentOutOfRangeException(tableExpression.Kind.ToString()); } return(null); }
private void AppendIntersectionWithPredecessor(IndentedStringBuilder.DelimitedScope delimited, TableExpression tableExpression, string tableAlias = null) { int predecessorIndex = FindRestrictingPredecessorTableExpressionIndex(); if (predecessorIndex >= 0) { delimited.BeginDelimitedElement(); string columnToSelect = (tableExpression.Kind == TableExpressionKind.Chain ? tableExpression.ChainLevel - 1 : tableExpression.ChainLevel) == 0 ? "Sid1" : "Sid2"; StringBuilder.Append(V1.Resource.ResourceSurrogateId, tableAlias).Append(" IN (SELECT ").Append(columnToSelect) .Append(" FROM ").Append(TableExpressionName(predecessorIndex)).Append(")"); } }
protected InsertCommand UpdateInsert(InsertCommand insert, TableExpression table, IEnumerable<ColumnAssignment> assignments) { if (table != insert.Table || assignments != insert.Assignments) { return new InsertCommand(table, assignments); } return insert; }
public override Expression GetUpdateExpression(MappingEntity entity, Expression instance, LambdaExpression updateCheck, LambdaExpression selector, Expression @else) { var tables = this.mapping.GetTables(entity); if (tables.Count < 2) { return base.GetUpdateExpression(entity, instance, updateCheck, selector, @else); } var commands = new List<Expression>(); foreach (var table in this.GetDependencyOrderedTables(entity)) { TableExpression tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(table)); var assignments = this.GetColumnAssignments(tex, instance, entity, (e, m) => this.mapping.GetAlias(e, m) == this.mapping.GetAlias(table) && this.mapping.IsUpdatable(e, m), null); var where = this.GetIdentityCheck(tex, entity, instance); commands.Add(new UpdateCommand(tex, where, assignments)); } if (selector != null) { commands.Add( new IFCommand( this.Translator.Linguist.Language.GetRowsAffectedExpression(commands[commands.Count-1]).GreaterThan(Expression.Constant(0)), this.GetUpdateResult(entity, instance, selector), @else ) ); } else if (@else != null) { commands.Add( new IFCommand( this.Translator.Linguist.Language.GetRowsAffectedExpression(commands[commands.Count-1]).LessThanOrEqual(Expression.Constant(0)), @else, null ) ); } Expression block = new BlockCommand(commands); if (updateCheck != null) { var test = this.GetEntityStateTest(entity, instance, updateCheck); return new IFCommand(test, block, null); } return block; }
protected UpdateCommand UpdateUpdate(UpdateCommand update, TableExpression table, Expression where, IEnumerable<ColumnAssignment> assignments) { if (table != update.Table || where != update.Where || assignments != update.Assignments) { return new UpdateCommand(table, where, assignments); } return update; }
private Expression GetIdentityCheck(TableExpression root, MappingEntity entity, Expression instance, MappingTable table) { if (this.mapping.IsExtensionTable(table)) { var keyColNames = this.mapping.GetExtensionKeyColumnNames(table).ToArray(); var relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToArray(); Expression where = null; for (int i = 0, n = keyColNames.Length; i < n; i++) { var relatedMember = relatedMembers[i]; var cex = new ColumnExpression(TypeHelper.GetMemberType(relatedMember), this.GetColumnType(entity, relatedMember), root.Alias, keyColNames[n]); var nex = this.GetMemberExpression(instance, entity, relatedMember); var eq = cex.Equal(nex); where = (where != null) ? where.And(eq) : where; } return where; } else { return base.GetIdentityCheck(root, entity, instance); } }
protected DeleteCommand UpdateDelete(DeleteCommand delete, TableExpression table, Expression where) { if (table != delete.Table || where != delete.Where) { return new DeleteCommand(table, where); } return delete; }
public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector) { var tables = this.mapping.GetTables(entity); if (tables.Count < 2) { return base.GetInsertExpression(entity, instance, selector); } var commands = new List<Expression>(); var map = this.GetDependentGeneratedColumns(entity); var vexMap = new Dictionary<MemberInfo, Expression>(); foreach (var table in this.GetDependencyOrderedTables(entity)) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table)); var assignments = this.GetColumnAssignments(tex, instance, entity, (e, m) => this.mapping.GetAlias(e, m) == this.mapping.GetAlias(table) && !this.mapping.IsGenerated(e, m), vexMap ); var totalAssignments = assignments.Concat( this.GetRelatedColumnAssignments(tex, entity, table, vexMap) ); commands.Add(new InsertCommand(tex, totalAssignments)); List<MemberInfo> members; if (map.TryGetValue(this.mapping.GetAlias(table), out members)) { var d = this.GetDependentGeneratedVariableDeclaration(entity, table, members, instance, vexMap); commands.Add(d); } } if (selector != null) { commands.Add(this.GetInsertResult(entity, instance, selector, vexMap)); } return new BlockCommand(commands); }
/// <summary> /// 返回插入具体实体时的 <see cref="ColumnAssignment"/> 集合。 /// </summary> /// <param name="syntax"></param> /// <param name="table"></param> /// <param name="entity">具体的实体。</param> /// <returns></returns> private static IEnumerable <ColumnAssignment> GetInsertArguments(ISyntaxProvider syntax, TableExpression table, IEntity entity) { var properties = GetModifiedProperties(entity); var assignments = properties .Select(m => new ColumnAssignment( (ColumnExpression)GetMemberExpression(table, m), Expression.Constant(GetConvertableValue(entity, m)) )).ToList(); assignments.AddRange(GetAssignmentsForPrimaryKeys(syntax, table, null, entity)); return(assignments); }
protected override Expression VisitTable(TableExpression table) { this.aliases.Add(table.Alias); return table; }
private NewArrayExpression CreateRelatedEntitiesLoaders <TRelatedEntitiesLoader>( IQuerySource querySource, IEnumerable <INavigation> navigationPath) { var queryContextParameter = Expression.Parameter(typeof(QueryContext)); var relatedEntitiesLoaders = new List <Expression <Func <QueryContext, TRelatedEntitiesLoader> > >(); var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var compositePredicateExpressionVisitor = _compositePredicateExpressionVisitorFactory.Create(); var targetTableExpression = selectExpression.GetTableForQuerySource(querySource); var canProduceInnerJoin = true; var navigationCount = 0; foreach (var navigation in navigationPath) { var queryIndex = _queryIndexes[navigationCount]; navigationCount++; var targetEntityType = navigation.GetTargetType(); var targetTableName = _relationalAnnotationProvider.For(targetEntityType).TableName; var targetTableAlias = _queryCompilationContext .CreateUniqueTableAlias(targetTableName[0].ToString().ToLowerInvariant()); if (!navigation.IsCollection()) { var joinedTableExpression = new TableExpression( targetTableName, _relationalAnnotationProvider.For(targetEntityType).Schema, targetTableAlias, querySource); var valueBufferOffset = selectExpression.Projection.Count; canProduceInnerJoin = canProduceInnerJoin && navigation.ForeignKey.IsRequired && navigation.IsDependentToPrincipal(); var joinExpression = canProduceInnerJoin ? selectExpression.AddInnerJoin(joinedTableExpression) : selectExpression.AddLeftOuterJoin(joinedTableExpression); var oldPredicate = selectExpression.Predicate; Dictionary <Type, int []> _; var materializer = _materializerFactory .CreateMaterializer( targetEntityType, selectExpression, (p, se) => se.AddToProjection( new AliasExpression( new ColumnExpression( _relationalAnnotationProvider.For(p).ColumnName, p, joinedTableExpression))) - valueBufferOffset, /*querySource:*/ null, out _); if (selectExpression.Predicate != oldPredicate) { compositePredicateExpressionVisitor.Visit(selectExpression); var newJoinExpression = AdjustJoinExpression(selectExpression, joinExpression); selectExpression.Predicate = oldPredicate; selectExpression.RemoveTable(joinExpression); selectExpression.AddTable(newJoinExpression); joinExpression = newJoinExpression; } joinExpression.Predicate = BuildJoinEqualityExpression( navigation, navigation.IsDependentToPrincipal() ? targetTableExpression : joinExpression, navigation.IsDependentToPrincipal() ? joinExpression : targetTableExpression, querySource); targetTableExpression = joinedTableExpression; relatedEntitiesLoaders.Add( Expression.Lambda <Func <QueryContext, TRelatedEntitiesLoader> >( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateReferenceRelatedEntitiesLoaderMethod, Expression.Constant(valueBufferOffset), Expression.Constant(queryIndex), materializer ), queryContextParameter)); } else { var principalTable = selectExpression.Tables.Count == 1 && selectExpression.Tables .OfType <SelectExpression>() .Any(s => s.Tables.Any(t => t.QuerySource == querySource)) // true when select is wrapped e.g. when RowNumber paging is enabled ? selectExpression.Tables[0] : selectExpression.Tables.Last(t => t.QuerySource == querySource); var canGenerateExists = selectExpression.Offset == null && selectExpression.Limit == null && !IsOrderingOnNonPrincipalKeyProperties( selectExpression.OrderBy, navigation.ForeignKey.PrincipalKey.Properties); foreach (var property in navigation.ForeignKey.PrincipalKey.Properties) { selectExpression .AddToOrderBy( _relationalAnnotationProvider.For(property).ColumnName, property, principalTable, OrderingDirection.Asc); } var targetSelectExpression = _selectExpressionFactory.Create(_queryCompilationContext); targetTableExpression = new TableExpression( targetTableName, _relationalAnnotationProvider.For(targetEntityType).Schema, targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); Dictionary <Type, int[]> _; var materializer = _materializerFactory .CreateMaterializer( targetEntityType, targetSelectExpression, (p, se) => se.AddToProjection( _relationalAnnotationProvider.For(p).ColumnName, p, querySource), /*querySource:*/ null, out _); if (canGenerateExists) { var subqueryExpression = selectExpression.Clone(); subqueryExpression.ClearProjection(); subqueryExpression.ClearOrderBy(); subqueryExpression.IsProjectStar = false; var subqueryTable = subqueryExpression.Tables.Count == 1 && subqueryExpression.Tables .OfType <SelectExpression>() .Any(s => s.Tables.Any(t => t.QuerySource == querySource)) // true when select is wrapped e.g. when RowNumber paging is enabled ? subqueryExpression.Tables[0] : subqueryExpression.Tables.Last(t => t.QuerySource == querySource); var existsPredicateExpression = new ExistsExpression(subqueryExpression); AddToPredicate(targetSelectExpression, existsPredicateExpression); AddToPredicate( subqueryExpression, BuildJoinEqualityExpression(navigation, targetTableExpression, subqueryTable, querySource)); compositePredicateExpressionVisitor.Visit(subqueryExpression); var pkPropertiesToFkPropertiesMap = navigation.ForeignKey.PrincipalKey.Properties .Zip(navigation.ForeignKey.Properties, (k, v) => new { PkProperty = k, FkProperty = v }) .ToDictionary(x => x.PkProperty, x => x.FkProperty); foreach (var ordering in selectExpression.OrderBy) { // ReSharper disable once PossibleNullReferenceException var principalKeyProperty = ((ordering.Expression as AliasExpression)?.Expression as ColumnExpression).Property; var referencedForeignKeyProperty = pkPropertiesToFkPropertiesMap[principalKeyProperty]; targetSelectExpression .AddToOrderBy( _relationalAnnotationProvider.For(referencedForeignKeyProperty).ColumnName, referencedForeignKeyProperty, targetTableExpression, ordering.OrderingDirection); } } else { var innerJoinSelectExpression = selectExpression.Clone( selectExpression.OrderBy .Select(o => o.Expression) .Last(o => o.IsAliasWithColumnExpression()) .TryGetColumnExpression().TableAlias); innerJoinSelectExpression.ClearProjection(); var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); LiftOrderBy(innerJoinSelectExpression, targetSelectExpression, innerJoinExpression); innerJoinSelectExpression.IsDistinct = true; innerJoinExpression.Predicate = BuildJoinEqualityExpression( navigation, targetTableExpression, innerJoinExpression, querySource); } compositePredicateExpressionVisitor.Visit(targetSelectExpression); selectExpression = targetSelectExpression; relatedEntitiesLoaders.Add( Expression.Lambda <Func <QueryContext, TRelatedEntitiesLoader> >( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateCollectionRelatedEntitiesLoaderMethod, queryContextParameter, Expression.Constant( _shaperCommandContextFactory.Create(() => SelectExpressionDependencies.QuerySqlGeneratorFactory.CreateDefault(targetSelectExpression))), Expression.Constant(queryIndex), materializer ), queryContextParameter)); } } return(Expression.NewArrayInit( typeof(Func <QueryContext, TRelatedEntitiesLoader>), relatedEntitiesLoaders)); }