From b5380ca73207c84ab6bd1f0043b3eb245e7577d4 Mon Sep 17 00:00:00 2001 From: Amersek <43096180+Amersek@users.noreply.github.com> Date: Mon, 23 Dec 2019 11:14:21 +0100 Subject: [PATCH 1/5] Update OracleDatabaseModelFactory.cs --- .../Internal/OracleDatabaseModelFactory.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs index ea811d9..ef7617f 100644 --- a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs +++ b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs @@ -137,12 +137,12 @@ private void GetTables( { var commandText = @" SELECT - t.tablespace_name AS schema, + user AS schema, t.table_name AS name FROM user_tables t "; var filter = - $"WHERE t.table_name <> '{HistoryRepository.DefaultTableName}' {(tableFilter != null ? $" AND {tableFilter("t.tablespace_name", "t.table_name")}" : "")}"; + $"WHERE t.table_name <> '{HistoryRepository.DefaultTableName}' {(tableFilter != null ? $" AND {tableFilter("user", "t.table_name")}" : "")}"; command.CommandText = commandText + filter; @@ -183,7 +183,7 @@ private void GetColumns( command.CommandText = new StringBuilder() .AppendLine("SELECT") - .AppendLine(" t.tablespace_name,") + .AppendLine(" user,") .AppendLine(" c.table_name,") .AppendLine(" c.column_name,") .AppendLine(" c.column_id,") @@ -206,7 +206,7 @@ private void GetColumns( { var tableColumnGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("user"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableColumnGroup in tableColumnGroups) @@ -277,7 +277,7 @@ private void GetKeys( { command.CommandText = new StringBuilder() .AppendLine("SELECT") - .AppendLine(" t.tablespace_name,") + .AppendLine(" user,") .AppendLine(" a.table_name,") .AppendLine(" a.column_name,") .AppendLine(" c.delete_rule,") @@ -296,7 +296,7 @@ private void GetKeys( { var tableIndexGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("user"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableIndexGroup in tableIndexGroups) @@ -374,7 +374,8 @@ private void GetForeignKeys( using (var command = connection.CreateCommand()) { command.CommandText = new StringBuilder() - .AppendLine("SELECT t.tablespace_name,") + .AppendLine("SELECT") + .AppendLine(" user,") .AppendLine(" x.table_name,") .AppendLine(" x.column_name,") .AppendLine(" c.table_name principal_table_name,") @@ -397,7 +398,7 @@ private void GetForeignKeys( { var tableForeignKeyGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("user"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableForeignKeyGroup in tableForeignKeyGroups) @@ -410,7 +411,7 @@ private void GetForeignKeys( var foreignKeyGroups = tableForeignKeyGroup .GroupBy( c => (Name: c.GetValueOrDefault("constraint_name"), - PrincipalTableSchema: c.GetValueOrDefault("tablespace_name"), + PrincipalTableSchema: c.GetValueOrDefault("user"), PrincipalTableName: c.GetValueOrDefault("principal_table_name"), OnDeleteAction: c.GetValueOrDefault("delete_rule"))); @@ -497,7 +498,7 @@ private void GetIndexes( { var queryBuilder = new StringBuilder() .AppendLine("SELECT") - .AppendLine(" b.tablespace_name,") + .AppendLine(" user,") .AppendLine(" b.uniqueness,") .AppendLine(" a.index_name,") .AppendLine(" a.table_name,") @@ -516,7 +517,7 @@ private void GetIndexes( { var tableIndexGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("user"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableIndexGroup in tableIndexGroups) @@ -567,7 +568,7 @@ private string GetDefaultSchema(DbConnection connection) { using (var command = connection.CreateCommand()) { - command.CommandText = "SELECT default_tablespace FROM user_users"; + command.CommandText = "SELECT username FROM user_users"; if (command.ExecuteScalar() is string schema) { From 889dfd221fea856632536a5d9c932617d2e30f49 Mon Sep 17 00:00:00 2001 From: Amersek <43096180+Amersek@users.noreply.github.com> Date: Thu, 26 Dec 2019 09:38:22 +0100 Subject: [PATCH 2/5] Update OracleDatabaseModelFactory.cs --- .../Internal/OracleDatabaseModelFactory.cs | 778 +++++++++++------- 1 file changed, 467 insertions(+), 311 deletions(-) diff --git a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs index ef7617f..16d0a91 100644 --- a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs +++ b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs @@ -75,6 +75,7 @@ public virtual DatabaseModel Create(string connectionString, IEnumerable /// public virtual DatabaseModel Create(DbConnection connection, IEnumerable tables, IEnumerable schemas) { + while (!System.Diagnostics.Debugger.IsAttached) { } Check.NotNull(connection, nameof(connection)); Check.NotNull(tables, nameof(tables)); Check.NotNull(schemas, nameof(schemas)); @@ -95,7 +96,7 @@ public virtual DatabaseModel Create(DbConnection connection, IEnumerable var tableList = tables.ToList(); var tableFilter = GenerateTableFilter(tableList.Select(Parse).ToList(), schemaFilter); - GetTables(connection, tableFilter, databaseModel); + GetTables(connection, tableFilter, databaseModel.DefaultSchema, schemaFilter, databaseModel, schemaList); foreach (var schema in schemaList .Except( @@ -131,20 +132,38 @@ public virtual DatabaseModel Create(DbConnection connection, IEnumerable private void GetTables( DbConnection connection, Func tableFilter, - DatabaseModel databaseModel) + string defaultSchema, + Func schemaFilter, + DatabaseModel databaseModel, + List schemaList) { using (var command = connection.CreateCommand()) { - var commandText = @" -SELECT - user AS schema, - t.table_name AS name -FROM user_tables t "; - var filter = - $"WHERE t.table_name <> '{HistoryRepository.DefaultTableName}' {(tableFilter != null ? $" AND {tableFilter("user", "t.table_name")}" : "")}"; + $"WHERE (t.table_name <> '{HistoryRepository.DefaultTableName}' AND t.owner = '{defaultSchema}' {(tableFilter != null ? $@" AND {tableFilter("t.owner", "t.table_name")})" : ")")}"; + + var filterSchema = + $"WHERE t.table_name <> '{HistoryRepository.DefaultTableName}' AND t.owner <> '{defaultSchema}' {(schemaFilter != null ? $@"AND {schemaFilter("t.owner")}" : "AND 1=2")} AND rpc.table_name = t.table_name"; + var commandText = $@" +SELECT + t.owner AS schema, + t.table_name AS name +FROM all_tables t + {filter} +UNION ALL +SELECT + t.owner AS schema, + t.table_name AS name +FROM all_tables t + WHERE EXISTS( + SELECT 1 + FROM all_constraints rc + INNER JOIN all_cons_columns rpc + ON rpc.constraint_name = rc.r_constraint_name AND rpc.owner = rc.r_owner + {filterSchema} + )"; - command.CommandText = commandText + filter; + command.CommandText = commandText; using (var reader = command.ExecuteReader()) { @@ -165,6 +184,12 @@ t.table_name AS name } } + var schemaFilter2 = GenerateSchemaFilter2(schemaList, databaseModel.DefaultSchema); + var tableFilter2 = GenerateTableFilter2(databaseModel.Tables.ToList()); + + filter = + $"WHERE (t.table_name <> '{HistoryRepository.DefaultTableName}' {(schemaFilter2 != null ? $@"AND {schemaFilter2("t.owner")}" : "")} {(tableFilter2 != null ? $@" AND {tableFilter2("t.owner", "t.table_name")}" : "")})"; + GetColumns(connection, filter, databaseModel); GetKeys(connection, filter, databaseModel); GetIndexes(connection, filter, databaseModel); @@ -183,7 +208,7 @@ private void GetColumns( command.CommandText = new StringBuilder() .AppendLine("SELECT") - .AppendLine(" user,") + .AppendLine(" t.owner,") .AppendLine(" c.table_name,") .AppendLine(" c.column_name,") .AppendLine(" c.column_id,") @@ -192,76 +217,88 @@ private void GetColumns( .AppendLine(" c.data_precision,") .AppendLine(" c.data_scale,") .AppendLine(" c.nullable,") - .AppendLine(" c.identity_column,") + .AppendLine(" 'NO' identity_column,") .AppendLine(" c.data_default,") .AppendLine(" c.virtual_column") - .AppendLine("FROM user_tab_cols c") - .AppendLine("INNER JOIN user_tables t ") - .AppendLine("ON UPPER(t.table_name)=UPPER(c.table_name)") + .AppendLine("FROM all_tab_cols c") + .AppendLine(" INNER JOIN all_tables t ") + .AppendLine(" ON UPPER(t.table_name)=UPPER(c.table_name)") .AppendLine(tableFilter) - .AppendLine("ORDER BY c.column_id") + .AppendLine("ORDER BY t.owner") .ToString(); - using (var reader = command.ExecuteReader()) + using (var reader = command.ExecuteReader()) { var tableColumnGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("user"), + ddr => (tableSchema: ddr.GetValueOrDefault("owner"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableColumnGroup in tableColumnGroups) { var tableSchema = tableColumnGroup.Key.tableSchema; var tableName = tableColumnGroup.Key.tableName; - var table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); + var table = (DatabaseTable) null; + try + { + table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName) ; + } catch + { + table = null; + } + if (table != null) { foreach (var dataRecord in tableColumnGroup) { - var columnName = dataRecord.GetValueOrDefault("column_name"); - var ordinal = dataRecord.GetValueOrDefault("column_id"); - var dataTypeName = dataRecord.GetValueOrDefault("data_type"); - var maxLength = dataRecord.GetValueOrDefault("data_length"); - var precision = dataRecord.GetValueOrDefault("data_precision"); - var scale = dataRecord.GetValueOrDefault("data_scale"); - var isNullable = dataRecord.GetValueOrDefault("nullable").Equals("Y"); - var isIdentity = dataRecord.GetValueOrDefault("identity_column").Equals("YES"); - var defaultValue = !isIdentity ? dataRecord.GetValueOrDefault("data_default") : null; - var computedValue = dataRecord.GetValueOrDefault("virtual_column").Equals("YES") ? defaultValue : null; - - var storeType = GetOracleClrType(dataTypeName, maxLength, precision, scale); - if (string.IsNullOrWhiteSpace(defaultValue) - || !string.IsNullOrWhiteSpace(computedValue)) - { - defaultValue = null; + if (table != null) + { + var columnName = dataRecord.GetValueOrDefault("column_name"); + var ordinal = dataRecord.GetValueOrDefault("column_id"); + var dataTypeName = dataRecord.GetValueOrDefault("data_type"); + var maxLength = dataRecord.GetValueOrDefault("data_length"); + var precision = dataRecord.GetValueOrDefault("data_precision"); + var scale = dataRecord.GetValueOrDefault("data_scale"); + var isNullable = dataRecord.GetValueOrDefault("nullable").Equals("Y"); + var isIdentity = dataRecord.GetValueOrDefault("identity_column").Equals("YES"); + var defaultValue = !isIdentity ? dataRecord.GetValueOrDefault("data_default") : null; + var computedValue = dataRecord.GetValueOrDefault("virtual_column").Equals("YES") ? defaultValue : null; + + var storeType = GetOracleClrType(dataTypeName, maxLength, precision, scale); + if (string.IsNullOrWhiteSpace(defaultValue) + || !string.IsNullOrWhiteSpace(computedValue)) + { + defaultValue = null; + } + + _logger.ColumnFound( + DisplayName(tableSchema, tableName), + columnName, + ordinal, + dataTypeName, + maxLength, + precision, + scale, + isNullable, + isIdentity, + defaultValue, + computedValue); + + var column = new DatabaseColumn + { + Table = table, + Name = columnName, + StoreType = storeType, + IsNullable = isNullable, + DefaultValueSql = defaultValue, + ComputedColumnSql = computedValue, + ValueGenerated = isIdentity + ? ValueGenerated.OnAdd + : default(ValueGenerated?) + }; + + table.Columns.Add(column); + } } - - _logger.ColumnFound( - DisplayName(tableSchema, tableName), - columnName, - ordinal, - dataTypeName, - maxLength, - precision, - scale, - isNullable, - isIdentity, - defaultValue, - computedValue); - - var column = new DatabaseColumn - { - Table = table, - Name = columnName, - StoreType = storeType, - IsNullable = isNullable, - DefaultValueSql = defaultValue, - ComputedColumnSql = computedValue, - ValueGenerated = isIdentity - ? ValueGenerated.OnAdd - : default(ValueGenerated?) - }; - - table.Columns.Add(column); } } } @@ -277,26 +314,28 @@ private void GetKeys( { command.CommandText = new StringBuilder() .AppendLine("SELECT") - .AppendLine(" user,") - .AppendLine(" a.table_name,") - .AppendLine(" a.column_name,") + .AppendLine(" t.owner,") + .AppendLine(" c.table_name,") + .AppendLine(" cc.column_name,") .AppendLine(" c.delete_rule,") - .AppendLine(" a.constraint_name,") + .AppendLine(" c.constraint_name,") .AppendLine(" c.constraint_type") - .AppendLine("FROM all_cons_columns a") - .AppendLine("JOIN all_constraints c") - .AppendLine(" ON a.CONSTRAINT_NAME = c.CONSTRAINT_NAME") - .AppendLine("INNER JOIN user_tables t") - .AppendLine(" ON t.table_name = a.table_name ") + .AppendLine("FROM all_constraints c") + .AppendLine(" INNER JOIN all_tables t") + .AppendLine(" ON UPPER(t.table_name) = UPPER(c.table_name) and t.owner = c.owner") + .AppendLine(" INNER JOIN all_cons_columns cc") + .AppendLine(" ON cc.constraint_name = c.constraint_name and cc.owner = t.owner") .AppendLine(tableFilter) .AppendLine(" AND c.constraint_type IN ('P','U') ") + .AppendLine("ORDER BY t.owner") .ToString(); using (var reader = command.ExecuteReader()) { var tableIndexGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("user"), + //ddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("owner"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableIndexGroup in tableIndexGroups) @@ -304,62 +343,73 @@ private void GetKeys( var tableSchema = tableIndexGroup.Key.tableSchema; var tableName = tableIndexGroup.Key.tableName; - var table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); + var table = (DatabaseTable)null; + try + { + table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); + } + catch + { + table = null; + } - var primaryKeyGroups = tableIndexGroup + if (table != null) + { + var primaryKeyGroups = tableIndexGroup .Where(ddr => ddr.GetValueOrDefault("constraint_type").Equals("P")) .GroupBy(ddr => ddr.GetValueOrDefault("constraint_name")) .ToArray(); - if (primaryKeyGroups.Length == 1) - { - var primaryKeyGroup = primaryKeyGroups[0]; + if (primaryKeyGroups.Length == 1) + { + var primaryKeyGroup = primaryKeyGroups[0]; - _logger.PrimaryKeyFound(primaryKeyGroup.Key, DisplayName(tableSchema, tableName)); + _logger.PrimaryKeyFound(primaryKeyGroup.Key, DisplayName(tableSchema, tableName)); - var primaryKey = new DatabasePrimaryKey - { - Table = table, - Name = primaryKeyGroup.Key - }; + var primaryKey = new DatabasePrimaryKey + { + Table = table, + Name = primaryKeyGroup.Key + }; - foreach (var dataRecord in primaryKeyGroup) - { - var columnName = dataRecord.GetValueOrDefault("column_name"); - var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + foreach (var dataRecord in primaryKeyGroup) + { + var columnName = dataRecord.GetValueOrDefault("column_name"); + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + + primaryKey.Columns.Add(column); + } - primaryKey.Columns.Add(column); + table.PrimaryKey = primaryKey; } - table.PrimaryKey = primaryKey; - } + var uniqueConstraintGroups = tableIndexGroup + .Where(ddr => ddr.GetValueOrDefault("constraint_type").Equals("U")) + .GroupBy(ddr => ddr.GetValueOrDefault("constraint_name")) + .ToArray(); - var uniqueConstraintGroups = tableIndexGroup - .Where(ddr => ddr.GetValueOrDefault("constraint_type").Equals("U")) - .GroupBy(ddr => ddr.GetValueOrDefault("constraint_name")) - .ToArray(); + foreach (var uniqueConstraintGroup in uniqueConstraintGroups) + { + _logger.UniqueConstraintFound(uniqueConstraintGroup.Key, DisplayName(tableSchema, tableName)); - foreach (var uniqueConstraintGroup in uniqueConstraintGroups) - { - _logger.UniqueConstraintFound(uniqueConstraintGroup.Key, DisplayName(tableSchema, tableName)); + var uniqueConstraint = new DatabaseUniqueConstraint + { + Table = table, + Name = uniqueConstraintGroup.Key + }; - var uniqueConstraint = new DatabaseUniqueConstraint - { - Table = table, - Name = uniqueConstraintGroup.Key - }; + foreach (var dataRecord in uniqueConstraintGroup) + { + var columnName = dataRecord.GetValueOrDefault("column_name"); + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); - foreach (var dataRecord in uniqueConstraintGroup) - { - var columnName = dataRecord.GetValueOrDefault("column_name"); - var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + uniqueConstraint.Columns.Add(column); + } - uniqueConstraint.Columns.Add(column); + table.UniqueConstraints.Add(uniqueConstraint); } - - table.UniqueConstraints.Add(uniqueConstraint); } } } @@ -374,31 +424,32 @@ private void GetForeignKeys( using (var command = connection.CreateCommand()) { command.CommandText = new StringBuilder() - .AppendLine("SELECT") - .AppendLine(" user,") - .AppendLine(" x.table_name,") - .AppendLine(" x.column_name,") - .AppendLine(" c.table_name principal_table_name,") - .AppendLine(" r.delete_rule,") - .AppendLine(" r.constraint_name,") - .AppendLine(" c.column_name principal_column_name") - .AppendLine("FROM all_cons_columns x,") - .AppendLine(" all_cons_columns c,") - .AppendLine(" all_constraints r,") - .AppendLine(" user_tables t") - .AppendLine(tableFilter) - .AppendLine(" AND x.constraint_name = r.constraint_name") - .AppendLine(" AND t.table_name = x.table_name") - .AppendLine(" AND c.constraint_name = r.r_constraint_name") - .AppendLine(" AND c.owner = r.r_owner") - .AppendLine(" AND r.constraint_type = 'R'") - .ToString(); + .AppendLine("SELECT") + .AppendLine(" t.owner,") + .AppendLine(" ric.constraint_name,") + .AppendLine(" ric.table_name,") + .AppendLine(" rc.column_name,") + .AppendLine(" rpc.column_name principal_column_name,") + .AppendLine(" rpc.table_name principal_table_name,") + .AppendLine(" ric.r_owner principal_schema,") + .AppendLine(" ric.delete_rule") + .AppendLine("FROM all_constraints ric") + .AppendLine(" INNER JOIN all_tables t") + .AppendLine(" ON t.table_name = ric.table_name AND t.owner = ric.owner") + .AppendLine(" INNER JOIN all_cons_columns rc") + .AppendLine(" ON rc.constraint_name = ric.constraint_name AND rc.table_name = ric.table_name AND rc.owner = ric.owner") + .AppendLine(" INNER JOIN all_cons_columns rpc") + .AppendLine(" ON rpc.constraint_name = ric.r_constraint_name AND rpc.owner = ric.r_owner") + .AppendLine(tableFilter) + .AppendLine("ORDER BY ric.owner, ric.constraint_name, ric.table_name") + .ToString(); using (var reader = command.ExecuteReader()) { var tableForeignKeyGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("user"), + //ddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("owner"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableForeignKeyGroup in tableForeignKeyGroups) @@ -406,82 +457,94 @@ private void GetForeignKeys( var tableSchema = tableForeignKeyGroup.Key.tableSchema; var tableName = tableForeignKeyGroup.Key.tableName; - var table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); - - var foreignKeyGroups = tableForeignKeyGroup - .GroupBy( - c => (Name: c.GetValueOrDefault("constraint_name"), - PrincipalTableSchema: c.GetValueOrDefault("user"), - PrincipalTableName: c.GetValueOrDefault("principal_table_name"), - OnDeleteAction: c.GetValueOrDefault("delete_rule"))); + var table = (DatabaseTable)null; + try + { + table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); + } + catch + { + table = null; + } - foreach (var foreignKeyGroup in foreignKeyGroups) + if (table != null) { - var fkName = foreignKeyGroup.Key.Name; - var principalTableSchema = foreignKeyGroup.Key.PrincipalTableSchema; - var principalTableName = foreignKeyGroup.Key.PrincipalTableName; - var onDeleteAction = foreignKeyGroup.Key.OnDeleteAction; - - _logger.ForeignKeyFound( - fkName, - DisplayName(table.Schema, table.Name), - DisplayName(principalTableSchema, principalTableName), - onDeleteAction); - - var principalTable = databaseModel.Tables.FirstOrDefault( - t => t.Schema == principalTableSchema - && t.Name == principalTableName) - ?? databaseModel.Tables.FirstOrDefault( - t => t.Schema.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) - && t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); - - if (principalTable == null) + var foreignKeyGroups = tableForeignKeyGroup + .GroupBy( + c => (Name: c.GetValueOrDefault("constraint_name"), + //Amer PrincipalTableSchema: c.GetValueOrDefault("tablespace_name"), + PrincipalTableSchema: c.GetValueOrDefault("principal_schema"), + PrincipalTableName: c.GetValueOrDefault("principal_table_name"), + OnDeleteAction: c.GetValueOrDefault("delete_rule"))); + + foreach (var foreignKeyGroup in foreignKeyGroups) { - _logger.ForeignKeyReferencesMissingPrincipalTableWarning( + var fkName = foreignKeyGroup.Key.Name; + var principalTableSchema = foreignKeyGroup.Key.PrincipalTableSchema; + var principalTableName = foreignKeyGroup.Key.PrincipalTableName; + var onDeleteAction = foreignKeyGroup.Key.OnDeleteAction; + + _logger.ForeignKeyFound( fkName, DisplayName(table.Schema, table.Name), - DisplayName(principalTableSchema, principalTableName)); + DisplayName(principalTableSchema, principalTableName), + onDeleteAction); - continue; - } - - var foreignKey = new DatabaseForeignKey - { - Name = fkName, - Table = table, - PrincipalTable = principalTable, - OnDelete = ConvertToReferentialAction(onDeleteAction) - }; + var principalTable = databaseModel.Tables.FirstOrDefault( + t => t.Schema == principalTableSchema + && t.Name == principalTableName) + ?? databaseModel.Tables.FirstOrDefault( + t => t.Schema.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) + && t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); - var invalid = false; - - foreach (var dataRecord in foreignKeyGroup) - { - var columnName = dataRecord.GetValueOrDefault("column_name"); - var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); - - var principalColumnName = dataRecord.GetValueOrDefault("principal_column_name"); - var principalColumn = foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name == principalColumnName) - ?? foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name.Equals(principalColumnName, StringComparison.OrdinalIgnoreCase)); - if (principalColumn == null) + if (principalTable == null) { - invalid = true; - _logger.ForeignKeyPrincipalColumnMissingWarning( + _logger.ForeignKeyReferencesMissingPrincipalTableWarning( fkName, DisplayName(table.Schema, table.Name), - principalColumnName, DisplayName(principalTableSchema, principalTableName)); - break; + + continue; } - foreignKey.Columns.Add(column); - foreignKey.PrincipalColumns.Add(principalColumn); - } + var foreignKey = new DatabaseForeignKey + { + Name = fkName, + Table = table, + PrincipalTable = principalTable, + OnDelete = ConvertToReferentialAction(onDeleteAction) + }; - if (!invalid) - { - table.ForeignKeys.Add(foreignKey); + var invalid = false; + + foreach (var dataRecord in foreignKeyGroup) + { + var columnName = dataRecord.GetValueOrDefault("column_name"); + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + + var principalColumnName = dataRecord.GetValueOrDefault("principal_column_name"); + var principalColumn = foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name == principalColumnName) + ?? foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name.Equals(principalColumnName, StringComparison.OrdinalIgnoreCase)); + if (principalColumn == null) + { + invalid = true; + _logger.ForeignKeyPrincipalColumnMissingWarning( + fkName, + DisplayName(table.Schema, table.Name), + principalColumnName, + DisplayName(principalTableSchema, principalTableName)); + break; + } + + foreignKey.Columns.Add(column); + foreignKey.PrincipalColumns.Add(principalColumn); + } + + if (!invalid) + { + table.ForeignKeys.Add(foreignKey); + } } } } @@ -498,18 +561,18 @@ private void GetIndexes( { var queryBuilder = new StringBuilder() .AppendLine("SELECT") - .AppendLine(" user,") - .AppendLine(" b.uniqueness,") - .AppendLine(" a.index_name,") - .AppendLine(" a.table_name,") - .AppendLine(" a.column_name") - .AppendLine("FROM all_ind_columns a") - .AppendLine("INNER JOIN all_indexes b") - .AppendLine(" ON a.index_name = b.index_name") - .AppendLine("INNER JOIN user_tables t") - .AppendLine(" ON t.table_name = a.table_name") + .AppendLine(" t.owner,") + .AppendLine(" i.uniqueness,") + .AppendLine(" i.index_name,") + .AppendLine(" i.table_name,") + .AppendLine(" ic.column_name") + .AppendLine("FROM all_indexes i") + .AppendLine("INNER JOIN all_tables t") + .AppendLine(" ON t.table_name = i.table_name AND t.owner = i.owner") + .AppendLine("INNER JOIN all_ind_columns ic") + .AppendLine(" ON ic.index_name = i.index_name AND ic.index_owner = t.owner") .AppendLine(tableFilter) - .AppendLine("ORDER BY a.table_name, a.index_name, a.column_position"); + .AppendLine("ORDER BY t.owner, i.table_name, i.index_name, ic.column_position"); command.CommandText = queryBuilder.ToString(); @@ -517,7 +580,8 @@ private void GetIndexes( { var tableIndexGroups = reader.Cast() .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("user"), + //Amerddr => (tableSchema: ddr.GetValueOrDefault("tablespace_name"), + ddr => (tableSchema: ddr.GetValueOrDefault("owner"), tableName: ddr.GetValueOrDefault("table_name"))); foreach (var tableIndexGroup in tableIndexGroups) @@ -525,36 +589,47 @@ private void GetIndexes( var tableSchema = tableIndexGroup.Key.tableSchema; var tableName = tableIndexGroup.Key.tableName; - var table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); - - var indexGroups = tableIndexGroup - .GroupBy( - ddr => - (Name: ddr.GetValueOrDefault("index_name"), - IsUnique: ddr.GetValueOrDefault("uniqueness").Equals("UNIQUE"))) - .ToArray(); - - foreach (var indexGroup in indexGroups) + var table = (DatabaseTable)null; + try + { + table = databaseModel.Tables.Single(t => t.Schema == tableSchema && t.Name == tableName); + } + catch { - _logger.IndexFound(indexGroup.Key.Name, DisplayName(tableSchema, tableName), indexGroup.Key.IsUnique); + table = null; + } - var index = new DatabaseIndex + if (table != null) + { + var indexGroups = tableIndexGroup + .GroupBy( + ddr => + (Name: ddr.GetValueOrDefault("index_name"), + IsUnique: ddr.GetValueOrDefault("uniqueness").Equals("UNIQUE"))) + .ToArray(); + + foreach (var indexGroup in indexGroups) { - Table = table, - Name = indexGroup.Key.Name, - IsUnique = indexGroup.Key.IsUnique - }; + _logger.IndexFound(indexGroup.Key.Name, DisplayName(tableSchema, tableName), indexGroup.Key.IsUnique); - foreach (var dataRecord in indexGroup) - { - var columnName = dataRecord.GetValueOrDefault("column_name"); - var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + var index = new DatabaseIndex + { + Table = table, + Name = indexGroup.Key.Name, + IsUnique = indexGroup.Key.IsUnique + }; - index.Columns.Add(column); - } + foreach (var dataRecord in indexGroup) + { + var columnName = dataRecord.GetValueOrDefault("column_name"); + var column = table.Columns.FirstOrDefault(c => c.Name == columnName) + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + + index.Columns.Add(column); + } - table.Indexes.Add(index); + table.Indexes.Add(index); + } } } } @@ -568,6 +643,7 @@ private string GetDefaultSchema(DbConnection connection) { using (var command = connection.CreateCommand()) { + //Amer command.CommandText = "SELECT default_tablespace FROM user_users"; command.CommandText = "SELECT username FROM user_users"; if (command.ExecuteScalar() is string schema) @@ -588,27 +664,27 @@ private static string GetOracleClrType(string dataTypeName, int maxLength, int p case "DECIMAL": case "NUMERIC": case "NUMBER": - { - if (precision == 0 - && scale == 0) { - precision = 10; - } - else if (precision > 10 - && scale > 0) - { - precision = 29; - scale = 4; - } - else if (precision < 6 - && scale == 0) - { - precision = 6; + if (precision == 0 + && scale == 0) + { + precision = 10; + } + else if (precision > 10 + && scale > 0) + { + precision = 29; + scale = 4; + } + else if (precision < 6 + && scale == 0) + { + precision = 6; + } + return scale > 0 + ? $"{dataTypeName}({precision},{scale})" + : $"{dataTypeName}({precision})"; } - return scale > 0 - ? $"{dataTypeName}({precision},{scale})" - : $"{dataTypeName}({precision})"; - } case "NVARCHAR2": case "NVARCHAR": case "VARCHAR": @@ -616,13 +692,13 @@ private static string GetOracleClrType(string dataTypeName, int maxLength, int p case "CHAR": case "NCLOB": case "CLOB": - { - if (maxLength < 0) { - return $"{dataTypeName}(4000)"; + if (maxLength < 0) + { + return $"{dataTypeName}(4000)"; + } + return $"{dataTypeName}({maxLength})"; } - return $"{dataTypeName}({maxLength})"; - } } return dataTypeName; @@ -646,16 +722,33 @@ private static Func GenerateSchemaFilter(IReadOnlyList s if (schemas.Count > 0) { return s => - { - var schemaFilterBuilder = new StringBuilder(); - schemaFilterBuilder.Append(s); - schemaFilterBuilder.Append(" IN ("); - schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral))); - schemaFilterBuilder.Append(")"); - return schemaFilterBuilder.ToString(); - }; + { + var schemaFilterBuilder = new StringBuilder(); + schemaFilterBuilder.Append(s); + schemaFilterBuilder.Append(" IN ("); + schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral))); + schemaFilterBuilder.Append(")"); + return schemaFilterBuilder.ToString(); + }; } + return null; + } + private static Func GenerateSchemaFilter2(IReadOnlyList schemas, string defaultSchema) + { + if (schemas.Count > 0) + { + return s => + { + var schemaFilterBuilder = new StringBuilder(); + schemaFilterBuilder.Append(s); + schemaFilterBuilder.Append(" IN ("); + schemaFilterBuilder.Append(EscapeLiteral(defaultSchema) + (schemas.Count > 0? ", " : "")); + schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral))); + schemaFilterBuilder.Append(")"); + return schemaFilterBuilder.ToString(); + }; + } return null; } @@ -674,76 +767,139 @@ private static (string Schema, string Table) Parse(string table) return string.IsNullOrEmpty(part2) ? (null, part1) : (part1, part2); } - private static Func GenerateTableFilter( - IReadOnlyList<(string Schema, string Table)> tables, - Func schemaFilter) + private static Func GenerateTableFilter2( + IList tables) { - if (schemaFilter != null - || tables.Count > 0) + if (tables.Count > 0) { return (s, t) => - { - var tableFilterBuilder = new StringBuilder(); + { + var tableFilterBuilder = new StringBuilder(); - var openBracket = false; - if (schemaFilter != null) + var openBracket = false; + if (tables.Count > 0) + { + if (openBracket) { tableFilterBuilder - .Append("(") - .Append(schemaFilter(s)); + .AppendLine() + .Append("OR "); + } + else + { + tableFilterBuilder.Append("("); openBracket = true; } - if (tables.Count > 0) + var tablesWithoutSchema = tables.Where(e => string.IsNullOrEmpty(e.Schema)).ToList(); + if (tablesWithoutSchema.Count > 0) { - if (openBracket) - { - tableFilterBuilder - .AppendLine() - .Append("OR "); - } - else - { - tableFilterBuilder.Append("("); - openBracket = true; - } + tableFilterBuilder.Append(t); + tableFilterBuilder.Append(" IN ("); + tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Name)))); + tableFilterBuilder.Append(")"); + } - var tablesWithoutSchema = tables.Where(e => string.IsNullOrEmpty(e.Schema)).ToList(); + var tablesWithSchema = tables.Where(e => !string.IsNullOrEmpty(e.Schema)).ToList(); + if (tablesWithSchema.Count > 0) + { if (tablesWithoutSchema.Count > 0) { - tableFilterBuilder.Append(t); - tableFilterBuilder.Append(" IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Table)))); - tableFilterBuilder.Append(")"); - } - - var tablesWithSchema = tables.Where(e => !string.IsNullOrEmpty(e.Schema)).ToList(); - if (tablesWithSchema.Count > 0) - { - if (tablesWithoutSchema.Count > 0) - { - tableFilterBuilder.Append(" OR "); - } - tableFilterBuilder.Append(t); - tableFilterBuilder.Append(" IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral(e.Table)))); - tableFilterBuilder.Append(") AND CONCAT("); - tableFilterBuilder.Append(s); - tableFilterBuilder.Append(", N'.', "); - tableFilterBuilder.Append(t); - tableFilterBuilder.Append(") IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Table}")))); - tableFilterBuilder.Append(")"); + tableFilterBuilder.Append(" OR "); } + tableFilterBuilder.Append(s); + tableFilterBuilder.Append("||N'.'||"); + tableFilterBuilder.Append(t); + tableFilterBuilder.Append(" IN ("); + tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Name}")))); + tableFilterBuilder.Append(")"); } + } + + if (openBracket) + { + tableFilterBuilder.Append(")"); + } + + return tableFilterBuilder.ToString(); + }; + } + + return null; + } + + private static Func GenerateTableFilter( + IReadOnlyList<(string Schema, string Table)> tables, + Func schemaFilter) + { + + if (tables.Count > 0) + { + return (s, t) => + { + var tableFilterBuilder = new StringBuilder(); + + var openBracket = false; + /* + if (schemaFilter != null) + { + tableFilterBuilder + .Append("(") + .Append(schemaFilter(s)); + openBracket = true; + } + */ + if (tables.Count > 0) + { if (openBracket) { + tableFilterBuilder + .AppendLine() + .Append("OR "); + } + else + { + tableFilterBuilder.Append("("); + openBracket = true; + } + + var tablesWithoutSchema = tables.Where(e => string.IsNullOrEmpty(e.Schema)).ToList(); + if (tablesWithoutSchema.Count > 0) + { + tableFilterBuilder.Append(t); + tableFilterBuilder.Append(" IN ("); + tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Table)))); + tableFilterBuilder.Append(")"); + } + + var tablesWithSchema = tables.Where(e => !string.IsNullOrEmpty(e.Schema)).ToList(); + if (tablesWithSchema.Count > 0) + { + if (tablesWithoutSchema.Count > 0) + { + tableFilterBuilder.Append(" OR "); + } + tableFilterBuilder.Append(t); + tableFilterBuilder.Append(" IN ("); + tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral(e.Table)))); + tableFilterBuilder.Append(") AND CONCAT("); + tableFilterBuilder.Append(s); + tableFilterBuilder.Append(", N'.', "); + tableFilterBuilder.Append(t); + tableFilterBuilder.Append(") IN ("); + tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Table}")))); tableFilterBuilder.Append(")"); } + } + + if (openBracket) + { + tableFilterBuilder.Append(")"); + } - return tableFilterBuilder.ToString(); - }; + return tableFilterBuilder.ToString(); + }; } return null; From f56e69684d37dce63a66ea99258d13a1fbaeb720 Mon Sep 17 00:00:00 2001 From: Amersek <43096180+Amersek@users.noreply.github.com> Date: Thu, 26 Dec 2019 09:57:42 +0100 Subject: [PATCH 3/5] Update OracleDatabaseModelFactory.cs --- .../Scaffolding/Internal/OracleDatabaseModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs index 16d0a91..ac024a1 100644 --- a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs +++ b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs @@ -75,7 +75,7 @@ public virtual DatabaseModel Create(string connectionString, IEnumerable /// public virtual DatabaseModel Create(DbConnection connection, IEnumerable tables, IEnumerable schemas) { - while (!System.Diagnostics.Debugger.IsAttached) { } + // for bebugging -- while (!System.Diagnostics.Debugger.IsAttached) { } Check.NotNull(connection, nameof(connection)); Check.NotNull(tables, nameof(tables)); Check.NotNull(schemas, nameof(schemas)); From bb8aa5162695c09d9915e505a0f0ba7dd522e83f Mon Sep 17 00:00:00 2001 From: Amer Isabegovic Date: Thu, 26 Dec 2019 14:21:37 +0100 Subject: [PATCH 4/5] Added ToUpper() for command line parameters --- .../Internal/OracleDatabaseModelFactory.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs index ac024a1..a7a4527 100644 --- a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs +++ b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs @@ -726,7 +726,7 @@ private static Func GenerateSchemaFilter(IReadOnlyList s var schemaFilterBuilder = new StringBuilder(); schemaFilterBuilder.Append(s); schemaFilterBuilder.Append(" IN ("); - schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral))); + schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral)).ToUpper()); schemaFilterBuilder.Append(")"); return schemaFilterBuilder.ToString(); }; @@ -743,8 +743,8 @@ private static Func GenerateSchemaFilter2(IReadOnlyList var schemaFilterBuilder = new StringBuilder(); schemaFilterBuilder.Append(s); schemaFilterBuilder.Append(" IN ("); - schemaFilterBuilder.Append(EscapeLiteral(defaultSchema) + (schemas.Count > 0? ", " : "")); - schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral))); + schemaFilterBuilder.Append(EscapeLiteral(defaultSchema.ToUpper()) + (schemas.Count > 0? ", " : "")); + schemaFilterBuilder.Append(string.Join(", ", schemas.Select(EscapeLiteral)).ToUpper()); schemaFilterBuilder.Append(")"); return schemaFilterBuilder.ToString(); }; @@ -796,7 +796,7 @@ private static Func GenerateTableFilter2( { tableFilterBuilder.Append(t); tableFilterBuilder.Append(" IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Name)))); + tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Name))).ToUpper()); tableFilterBuilder.Append(")"); } @@ -811,7 +811,7 @@ private static Func GenerateTableFilter2( tableFilterBuilder.Append("||N'.'||"); tableFilterBuilder.Append(t); tableFilterBuilder.Append(" IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Name}")))); + tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Name}"))).ToUpper()); tableFilterBuilder.Append(")"); } } @@ -869,7 +869,7 @@ private static Func GenerateTableFilter( { tableFilterBuilder.Append(t); tableFilterBuilder.Append(" IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Table)))); + tableFilterBuilder.Append(string.Join(", ", tablesWithoutSchema.Select(e => EscapeLiteral(e.Table))).ToUpper()); tableFilterBuilder.Append(")"); } @@ -882,13 +882,13 @@ private static Func GenerateTableFilter( } tableFilterBuilder.Append(t); tableFilterBuilder.Append(" IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral(e.Table)))); + tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral(e.Table))).ToUpper()); tableFilterBuilder.Append(") AND CONCAT("); tableFilterBuilder.Append(s); tableFilterBuilder.Append(", N'.', "); tableFilterBuilder.Append(t); tableFilterBuilder.Append(") IN ("); - tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Table}")))); + tableFilterBuilder.Append(string.Join(", ", tablesWithSchema.Select(e => EscapeLiteral($"{e.Schema}.{e.Table}"))).ToUpper()); tableFilterBuilder.Append(")"); } } From 2315ebb9cf09621f1d48317063b4b4f9d5522296 Mon Sep 17 00:00:00 2001 From: Amer Isabegovic Date: Thu, 26 Dec 2019 16:43:24 +0100 Subject: [PATCH 5/5] In some cases entity columns was duplicated. (same tables in different schemas) --- .../Scaffolding/Internal/OracleDatabaseModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs index a7a4527..44ab6c5 100644 --- a/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs +++ b/src/OracleProvider/Scaffolding/Internal/OracleDatabaseModelFactory.cs @@ -222,7 +222,7 @@ private void GetColumns( .AppendLine(" c.virtual_column") .AppendLine("FROM all_tab_cols c") .AppendLine(" INNER JOIN all_tables t ") - .AppendLine(" ON UPPER(t.table_name)=UPPER(c.table_name)") + .AppendLine(" ON UPPER(t.table_name)=UPPER(c.table_name) AND t.owner = c.owner") .AppendLine(tableFilter) .AppendLine("ORDER BY t.owner") .ToString();