public QueryPlan GetQuery(string type, string[] paths, string[] includes = null) { var typeMapping = _metaInfoProvider.GetTypeMapping(type); var tables = typeMapping.Tables.OfType<EntityTable>().ToList(); var mainTable = tables.First(); var mainTableContext = GetTableContext(mainTable, "M"); var selectParts = new List<SelectPart>(); var selectBuilder = new SelectSqlBuilder(mainTableContext).SelectAll(mainTableContext); var mainPart = new TypePart { Type = typeMapping, Tables = new List<Table>(tables) }; selectParts.Add(mainPart); if (includes != null) { foreach (var include in includes) { selectParts.AddRange(Include(selectBuilder, mainTableContext, typeMapping, include)); } } foreach (var table in tables.Skip(1)) { var secondContext = GetTableContext(table, "T"); selectBuilder .SelectAll(secondContext) .InnerJoin(mainTableContext, secondContext, table.IdentityColumn.ColumnName, table.IdentityColumn.ColumnName); } foreach (var s in paths) { BuildSelectPredicate(selectBuilder, mainTableContext, typeMapping, s); } var selectClause = new SelectClause{ Parts = selectParts.ToArray() }; return new QueryPlan { SqlString = selectBuilder.GetSql(), SelectClause = selectClause }; }
private IEnumerable<SelectPart> Include(SelectSqlBuilder bulder, TableContext mainTableContext, TypeMappingInfo typeMapping, string include) { var fields = include.Split('.'); var currentType = typeMapping; var context = mainTableContext; foreach (var navigationField in fields) { var navProperty = (NavigationPropertyMapping) currentType.GetProperty(navigationField); if (navProperty.Table is PrimitiveListTable) { var listContext = GetTableContext(navProperty.Table, "S"); bulder.SelectAll(listContext); bulder.LeftOuterJoin(context, listContext, ((EntityTable)context.Table).IdentityColumn.ColumnName, navProperty.Table.Columns.First().ColumnName); yield return new ExpansionPart { Table = navProperty.Table, CollectingType = currentType, CollectingProperty = navProperty }; break; } //todo: no primitive collections totally and no inheritance lookup var targetType = navProperty.TargetType; var tableInfo = targetType.Tables.OfType<EntityTable>().First(); var nextcontext = GetTableContext(tableInfo, "S"); bulder.SelectAll(nextcontext); if (navProperty.Host == ReferenceHost.Parent) { bulder.LeftOuterJoin(context, nextcontext, navProperty.ColumnName, tableInfo.IdentityColumn.ColumnName); } else if (navProperty.Host == ReferenceHost.Child) { bulder.LeftOuterJoin(context, nextcontext, ((EntityTable)context.Table).IdentityColumn.ColumnName, navProperty.ColumnName); } else throw new NotImplementedException(); yield return new SubTypePart { Type = targetType, Tables = new[] {tableInfo}, CollectingType = currentType, CollectingProperty = navProperty }; currentType = targetType; context = nextcontext; } }