private static void generateDataAccessCodeForDatabase( Logger log, IDatabase database, string libraryBasePath, TextWriter writer, string baseNamespace, SystemDevelopmentConfiguration configuration) { var tableNames = DatabaseOps.GetDatabaseTables(database); if (configuration.database == null) { log.Info($"Configuration is missing the <{nameof( configuration.database )}> element."); return; } ensureTablesExist(tableNames, configuration.database.SmallTables, "small"); ensureTablesExist(tableNames, configuration.database.TablesUsingRowVersionedDataCaching, "row-versioned data caching"); ensureTablesExist(tableNames, configuration.database.revisionHistoryTables, "revision history"); ensureTablesExist(tableNames, configuration.database.WhitelistedTables, "whitelisted"); tableNames = tableNames.Where( table => configuration.database.WhitelistedTables == null || configuration.database.WhitelistedTables.Any(i => i.EqualsIgnoreCase(table))); database.ExecuteDbMethod( cn => { writer.WriteLine(); ConfigurationRetrievalStatics.Generate(writer, baseNamespace, configuration.database); // database logic access - standard writer.WriteLine(); TableConstantStatics.Generate(cn, writer, baseNamespace, database, tableNames); // database logic access - custom writer.WriteLine(); RowConstantStatics.Generate(cn, writer, baseNamespace, database, configuration.database); // retrieval and modification commands - standard writer.WriteLine(); CommandConditionStatics.Generate(cn, writer, baseNamespace, database, tableNames); writer.WriteLine(); var tableRetrievalNamespaceDeclaration = TableRetrievalStatics.GetNamespaceDeclaration(baseNamespace, database); TableRetrievalStatics.Generate(cn, writer, tableRetrievalNamespaceDeclaration, database, tableNames, configuration.database); writer.WriteLine(); var modNamespaceDeclaration = StandardModificationStatics.GetNamespaceDeclaration(baseNamespace, database); StandardModificationStatics.Generate(cn, writer, modNamespaceDeclaration, database, tableNames, configuration.database); foreach (var tableName in tableNames) { TableRetrievalStatics.WritePartialClass(cn, libraryBasePath, tableRetrievalNamespaceDeclaration, database, tableName); StandardModificationStatics.WritePartialClass( cn, libraryBasePath, modNamespaceDeclaration, database, tableName, DataAccessStatics.IsRevisionHistoryTable(tableName, configuration.database)); } // retrieval and modification commands - custom writer.WriteLine(); QueryRetrievalStatics.Generate(cn, writer, baseNamespace, database, configuration.database); writer.WriteLine(); CustomModificationStatics.Generate(cn, writer, baseNamespace, database, configuration.database); // other commands if (cn.DatabaseInfo is OracleInfo) { writer.WriteLine(); SequenceStatics.Generate(cn, writer, baseNamespace, database, configuration.database.CommandTimeoutSecondsTyped); writer.WriteLine(); ProcedureStatics.Generate(cn, writer, baseNamespace, database); } }); }
internal static void Generate(DBConnection cn, TextWriter writer, string namespaceDeclaration, IDatabase database, IEnumerable <Table> tables, Database configuration) { writer.WriteLine(namespaceDeclaration); foreach (var table in tables) { try { CodeGenerationStatics.AddSummaryDocComment(writer, "Contains logic that retrieves rows from the " + table + " table."); writer.WrapInTableNamespaceIfNecessary( table, () => { writer.WriteLine($"public static partial class {table.GetTableRetrievalClassDeclaration()} {{"); var isRevisionHistoryTable = DataAccessStatics.IsRevisionHistoryTable(table.Name, configuration); var columns = new TableColumns(cn, table.ObjectIdentifier, isRevisionHistoryTable); // Write nested classes. DataAccessStatics.WriteRowClasses( writer, columns.AllColumns, localWriter => { if (!isRevisionHistoryTable) { return; } writer.WriteLine( "public UserTransaction Transaction { get { return RevisionHistoryStatics.UserTransactionsById[ RevisionHistoryStatics.RevisionsById[ System.Convert.ToInt32( " + Utility.GetCSharpIdentifier(columns.PrimaryKeyAndRevisionIdColumn.PascalCasedNameExceptForOracle) + " ) ].UserTransactionId ]; } }"); }, localWriter => { if (!columns.DataColumns.Any()) { return; } var modClass = "Modification." + table.GetStandardModificationClassReference(); var revisionHistorySuffix = StandardModificationStatics.GetRevisionHistorySuffix(isRevisionHistoryTable); writer.WriteLine("public " + modClass + " ToModification" + revisionHistorySuffix + "() {"); writer.WriteLine( "return " + modClass + ".CreateForSingleRowUpdate" + revisionHistorySuffix + "( " + StringTools.ConcatenateWithDelimiter( ", ", columns.AllColumnsExceptRowVersion.Select(i => Utility.GetCSharpIdentifier(i.PascalCasedNameExceptForOracle)).ToArray()) + " );"); writer.WriteLine("}"); }); writeCacheClass( cn, writer, database, table, columns, isRevisionHistoryTable); var isSmallTable = configuration.SmallTables != null && configuration.SmallTables.Any(i => i.EqualsIgnoreCase(table.ObjectIdentifier)); var tableUsesRowVersionedCaching = configuration.TablesUsingRowVersionedDataCaching != null && configuration.TablesUsingRowVersionedDataCaching.Any(i => i.EqualsIgnoreCase(table.ObjectIdentifier)); if (tableUsesRowVersionedCaching && columns.RowVersionColumn == null && !(cn.DatabaseInfo is OracleInfo)) { throw new ApplicationException( cn.DatabaseInfo is MySqlInfo ? "Row-versioned data caching cannot currently be used with MySQL databases." : "Row-versioned data caching can only be used with the {0} table if you add a rowversion column.".FormatWith(table)); } if (isSmallTable) { writeGetAllRowsMethod(writer, isRevisionHistoryTable, false); } writeGetRowsMethod( cn, writer, database, table, columns, isSmallTable, tableUsesRowVersionedCaching, isRevisionHistoryTable, false, configuration.CommandTimeoutSecondsTyped); if (isRevisionHistoryTable) { if (isSmallTable) { writeGetAllRowsMethod(writer, true, true); } writeGetRowsMethod( cn, writer, database, table, columns, isSmallTable, tableUsesRowVersionedCaching, true, true, configuration.CommandTimeoutSecondsTyped); } writeGetRowMatchingPkMethod( cn, writer, database, table, columns, isSmallTable, tableUsesRowVersionedCaching, isRevisionHistoryTable, configuration.CommandTimeoutSecondsTyped); if (isRevisionHistoryTable) { DataAccessStatics.WriteGetLatestRevisionsConditionMethod(writer, columns.PrimaryKeyAndRevisionIdColumn.Name); } if (tableUsesRowVersionedCaching) { var keyTupleTypeArguments = getPkAndVersionTupleTypeArguments(cn, columns); writer.WriteLine($"private static Cache<{TypeNames.Tuple}<{keyTupleTypeArguments}>, BasicRow> getRowsByPkAndVersion() {{"); var first = $"VersionedRowDataCache<{TypeNames.Tuple}<{getPkTupleTypeArguments( columns )}>, {TypeNames.Tuple}<{keyTupleTypeArguments}>, BasicRow>"; var second = table.Name.TableNameToPascal(cn) + "TableRetrievalRowsByPkAndVersion"; var third = StringTools.ConcatenateWithDelimiter(", ", Enumerable.Range(1, columns.KeyColumns.Count()).Select(i => "i.Item{0}".FormatWith(i))); writer.WriteLine( $@"return AppMemoryCache.GetCacheValue<{first}>( ""{second}"", () => new {first}( i => {TypeNames.Tuple}.Create( {third} ) ) ).RowsByPkAndVersion;"); writer.WriteLine("}"); } // Initially we did not generate this method for small tables, but we found a need for it when the cache is disabled since that will cause // GetRowMatchingId to repeatedly query. if (columns.KeyColumns.Count() == 1 && columns.KeyColumns.Single().Name.ToLower().EndsWith("id")) { writeToIdDictionaryMethod(writer, columns); } writer.WriteLine("}"); // class }); } catch (Exception e) when(!(e is UserCorrectableException)) { throw new ApplicationException($"An error occurred while generating TableRetrieval logic for the '{table}' table.", e); } } writer.WriteLine("}"); // namespace }
private void generateDataAccessCodeForDatabase( RedStapler.StandardLibrary.InstallationSupportUtility.DatabaseAbstraction.Database database, string libraryBasePath, TextWriter writer, string baseNamespace, RedStapler.StandardLibrary.Configuration.SystemDevelopment.Database configuration) { // Ensure that all tables specified in the configuration file actually exist. var tableNames = DatabaseOps.GetDatabaseTables(database); ensureTablesExist(tableNames, configuration.SmallTables, "small"); ensureTablesExist(tableNames, configuration.TablesUsingRowVersionedDataCaching, "row-versioned data caching"); ensureTablesExist(tableNames, configuration.revisionHistoryTables, "revision history"); database.ExecuteDbMethod( delegate(DBConnection cn) { // database logic access - standard if (!configuration.EveryTableHasKeySpecified || configuration.EveryTableHasKey) { writer.WriteLine(); TableConstantStatics.Generate(cn, writer, baseNamespace, database); } // database logic access - custom writer.WriteLine(); RowConstantStatics.Generate(cn, writer, baseNamespace, database, configuration); // retrieval and modification commands - standard if (!configuration.EveryTableHasKeySpecified || configuration.EveryTableHasKey) { writer.WriteLine(); CommandConditionStatics.Generate(cn, writer, baseNamespace, database); writer.WriteLine(); var tableRetrievalNamespaceDeclaration = TableRetrievalStatics.GetNamespaceDeclaration(baseNamespace, database); TableRetrievalStatics.Generate(cn, writer, tableRetrievalNamespaceDeclaration, database, configuration); writer.WriteLine(); var modNamespaceDeclaration = StandardModificationStatics.GetNamespaceDeclaration(baseNamespace, database); StandardModificationStatics.Generate(cn, writer, modNamespaceDeclaration, database, configuration); foreach (var tableName in DatabaseOps.GetDatabaseTables(database)) { TableRetrievalStatics.WritePartialClass(cn, libraryBasePath, tableRetrievalNamespaceDeclaration, database, tableName); StandardModificationStatics.WritePartialClass( cn, libraryBasePath, modNamespaceDeclaration, database, tableName, CodeGeneration.DataAccess.DataAccessStatics.IsRevisionHistoryTable(tableName, configuration)); } } // retrieval and modification commands - custom writer.WriteLine(); QueryRetrievalStatics.Generate(cn, writer, baseNamespace, database, configuration); writer.WriteLine(); CustomModificationStatics.Generate(cn, writer, baseNamespace, database, configuration); // other commands if (cn.DatabaseInfo is OracleInfo) { writer.WriteLine(); SequenceStatics.Generate(cn, writer, baseNamespace, database); writer.WriteLine(); ProcedureStatics.Generate(cn, writer, baseNamespace, database); } }); }
private void generateDataAccessCodeForDatabase( InstallationSupportUtility.DatabaseAbstraction.Database database, string libraryBasePath, TextWriter writer, string baseNamespace, Configuration.SystemDevelopment.Database configuration) { var tableNames = DatabaseOps.GetDatabaseTables(database).ToImmutableArray(); ensureTablesExist(tableNames, configuration.SmallTables, "small"); ensureTablesExist(tableNames, configuration.TablesUsingRowVersionedDataCaching, "row-versioned data caching"); ensureTablesExist(tableNames, configuration.revisionHistoryTables, "revision history"); ensureTablesExist(tableNames, configuration.WhitelistedTables, "whitelisted"); tableNames = tableNames.Where(table => configuration.WhitelistedTables == null || configuration.WhitelistedTables.Any(i => i.EqualsIgnoreCase(table))) .ToImmutableArray(); database.ExecuteDbMethod( delegate(DBConnection cn) { // database logic access - standard writer.WriteLine(); TableConstantStatics.Generate(cn, writer, baseNamespace, database, tableNames); // database logic access - custom writer.WriteLine(); RowConstantStatics.Generate(cn, writer, baseNamespace, database, configuration); // retrieval and modification commands - standard writer.WriteLine(); CommandConditionStatics.Generate(cn, writer, baseNamespace, database, tableNames); writer.WriteLine(); var tableRetrievalNamespaceDeclaration = TableRetrievalStatics.GetNamespaceDeclaration(baseNamespace, database); TableRetrievalStatics.Generate(cn, writer, tableRetrievalNamespaceDeclaration, database, tableNames, configuration); writer.WriteLine(); var modNamespaceDeclaration = StandardModificationStatics.GetNamespaceDeclaration(baseNamespace, database); StandardModificationStatics.Generate(cn, writer, modNamespaceDeclaration, database, tableNames, configuration); foreach (var tableName in tableNames) { TableRetrievalStatics.WritePartialClass(cn, libraryBasePath, tableRetrievalNamespaceDeclaration, database, tableName); StandardModificationStatics.WritePartialClass( cn, libraryBasePath, modNamespaceDeclaration, database, tableName, CodeGeneration.DataAccess.DataAccessStatics.IsRevisionHistoryTable(tableName, configuration)); } // retrieval and modification commands - custom writer.WriteLine(); QueryRetrievalStatics.Generate(cn, writer, baseNamespace, database, configuration); writer.WriteLine(); CustomModificationStatics.Generate(cn, writer, baseNamespace, database, configuration); // other commands if (cn.DatabaseInfo is OracleInfo) { writer.WriteLine(); SequenceStatics.Generate(cn, writer, baseNamespace, database); writer.WriteLine(); ProcedureStatics.Generate(cn, writer, baseNamespace, database); } }); }
internal static void Generate( DBConnection cn, TextWriter writer, string namespaceDeclaration, Database database, IEnumerable <string> tableNames, Configuration.SystemDevelopment.Database configuration) { writer.WriteLine(namespaceDeclaration); foreach (var table in tableNames) { CodeGenerationStatics.AddSummaryDocComment(writer, "Contains logic that retrieves rows from the " + table + " table."); writer.WriteLine("public static partial class " + GetClassName(cn, table) + " {"); var isRevisionHistoryTable = DataAccessStatics.IsRevisionHistoryTable(table, configuration); var columns = new TableColumns(cn, table, isRevisionHistoryTable); // Write nested classes. DataAccessStatics.WriteRowClasses( writer, columns.AllColumns, localWriter => { if (!isRevisionHistoryTable) { return; } writer.WriteLine( "public UserTransaction Transaction { get { return RevisionHistoryStatics.UserTransactionsById[ RevisionHistoryStatics.RevisionsById[ System.Convert.ToInt32( " + EwlStatics.GetCSharpIdentifier(columns.PrimaryKeyAndRevisionIdColumn.PascalCasedNameExceptForOracle) + " ) ].UserTransactionId ]; } }"); }, localWriter => { if (!columns.DataColumns.Any()) { return; } var modClass = database.SecondaryDatabaseName + "Modification." + StandardModificationStatics.GetClassName(cn, table, isRevisionHistoryTable, isRevisionHistoryTable); var revisionHistorySuffix = StandardModificationStatics.GetRevisionHistorySuffix(isRevisionHistoryTable); writer.WriteLine("public " + modClass + " ToModification" + revisionHistorySuffix + "() {"); writer.WriteLine( "return " + modClass + ".CreateForSingleRowUpdate" + revisionHistorySuffix + "( " + StringTools.ConcatenateWithDelimiter( ", ", columns.AllColumnsExceptRowVersion.Select(i => EwlStatics.GetCSharpIdentifier(i.PascalCasedNameExceptForOracle)).ToArray()) + " );"); writer.WriteLine("}"); }); writeCacheClass(cn, writer, database, table, columns, isRevisionHistoryTable); var isSmallTable = configuration.SmallTables != null && configuration.SmallTables.Any(i => i.EqualsIgnoreCase(table)); var tableUsesRowVersionedCaching = configuration.TablesUsingRowVersionedDataCaching != null && configuration.TablesUsingRowVersionedDataCaching.Any(i => i.EqualsIgnoreCase(table)); if (tableUsesRowVersionedCaching && columns.RowVersionColumn == null && !(cn.DatabaseInfo is OracleInfo)) { throw new UserCorrectableException( cn.DatabaseInfo is MySqlInfo ? "Row-versioned data caching cannot currently be used with MySQL databases." : "Row-versioned data caching can only be used with the {0} table if you add a rowversion column.".FormatWith(table)); } if (isSmallTable) { writeGetAllRowsMethod(writer, isRevisionHistoryTable, false); } writeGetRowsMethod(cn, writer, database, table, columns, isSmallTable, tableUsesRowVersionedCaching, isRevisionHistoryTable, false); if (isRevisionHistoryTable) { if (isSmallTable) { writeGetAllRowsMethod(writer, true, true); } writeGetRowsMethod(cn, writer, database, table, columns, isSmallTable, tableUsesRowVersionedCaching, true, true); } writeGetRowMatchingPkMethod(cn, writer, database, table, columns, isSmallTable, tableUsesRowVersionedCaching, isRevisionHistoryTable); if (isRevisionHistoryTable) { DataAccessStatics.WriteGetLatestRevisionsConditionMethod(writer, columns.PrimaryKeyAndRevisionIdColumn.Name); } if (tableUsesRowVersionedCaching) { var keyTupleTypeArguments = getPkAndVersionTupleTypeArguments(cn, columns); writer.WriteLine("private static " + "Cache<System.Tuple<" + keyTupleTypeArguments + ">, BasicRow>" + " getRowsByPkAndVersion() {"); writer.WriteLine( "return AppMemoryCache.GetCacheValue<{0}>( \"{1}\", () => new {0}( i => System.Tuple.Create( {2} ) ) ).RowsByPkAndVersion;".FormatWith( "VersionedRowDataCache<System.Tuple<{0}>, System.Tuple<{1}>, BasicRow>".FormatWith(getPkTupleTypeArguments(columns), keyTupleTypeArguments), database.SecondaryDatabaseName + table.TableNameToPascal(cn) + "TableRetrievalRowsByPkAndVersion", StringTools.ConcatenateWithDelimiter(", ", Enumerable.Range(1, columns.KeyColumns.Count()).Select(i => "i.Item{0}".FormatWith(i)).ToArray()))); writer.WriteLine("}"); } // Initially we did not generate this method for small tables, but we found a need for it when the cache is disabled since that will cause // GetRowMatchingId to repeatedly query. if (columns.KeyColumns.Count() == 1 && columns.KeyColumns.Single().Name.ToLower().EndsWith("id")) { writeToIdDictionaryMethod(writer, columns); } if (isRevisionHistoryTable) { DataAccessStatics.WriteRevisionDeltaExtensionMethods(writer, GetClassName(cn, table), columns.DataColumns); } writer.WriteLine("}"); // class } writer.WriteLine("}"); // namespace }