internal static void Generate(TextWriter writer, string baseNamespace, Database configuration) { // NOTE SJR: Nothing is using this but they should be. writer.CodeBlock( $"namespace {baseNamespace} {{", () => writer.CodeBlock( $"public static class {className} {{", () => writer.WriteLine($@"public const int {commandTimeoutSecondsPropertyName} = {configuration.CommandTimeoutSecondsTyped?.ToString() ?? "null"};"))); }
private static void writeGetRowMatchingPkMethod( DBConnection cn, TextWriter writer, IDatabase database, Table table, TableColumns tableColumns, bool isSmallTable, bool tableUsesRowVersionedCaching, bool isRevisionHistoryTable, int?commandTimeoutSeconds) { var pkIsId = tableColumns.KeyColumns.Count() == 1 && tableColumns.KeyColumns.Single().Name.ToLower().EndsWith("id"); var methodName = pkIsId ? "GetRowMatchingId" : "GetRowMatchingPk"; var pkParameters = pkIsId ? tableColumns.KeyColumns.Single().DataTypeName + " id" : tableColumns.KeyColumns.Select(i => $"{i.DataTypeName} {i.CamelCasedName}").GetCommaDelimitedList(); const string returnNullIfNoMatch = nameof(returnNullIfNoMatch); const string id = nameof(id); writer.CodeBlock( $"public static Row {methodName}( {pkParameters}, bool {returnNullIfNoMatch} = false ) {{", () => { if (isSmallTable) { writer.WriteLine("var cache = Cache.Current;"); var commandConditionsExpression = isRevisionHistoryTable ? "new [] {getLatestRevisionsCondition()}" : "new InlineDbCommandCondition[ 0 ]"; writer.WriteLine("cache.Queries.GetResultSet( " + commandConditionsExpression + ", commandConditions => {"); writeResultSetCreatorBody( cn, writer, database, table, tableColumns, tableUsesRowVersionedCaching, isRevisionHistoryTable, "true", commandTimeoutSeconds); writer.WriteLine("} );"); var rowsByPkExpression = $"cache.{( isRevisionHistoryTable ? "LatestRevision" : "" )}RowsByPk"; var pkTupleCreationArguments = pkIsId ? id : StringTools.ConcatenateWithDelimiter(", ", tableColumns.KeyColumns.Select(i => i.CamelCasedName)); writer.WriteLine($"if( !{returnNullIfNoMatch} )"); writer.WriteLine($"return {rowsByPkExpression}[ {TypeNames.Tuple}.Create( {pkTupleCreationArguments} ) ];"); writer.WriteLine("Row row;"); writer.WriteLine($"return {rowsByPkExpression}.TryGetValue( {TypeNames.Tuple}.Create( {pkTupleCreationArguments} ), out row ) ? row : null;"); } else { var condition = pkIsId ? $"new {table.GetEqualityConditionClassReference( cn, tableColumns.KeyColumns.Single() )}( {id} )" : (from keyColumn in tableColumns.KeyColumns let className = table.GetEqualityConditionClassReference(cn, keyColumn) select $"new {className}( {keyColumn.CamelCasedName} )").GetCommaDelimitedList(); writer.WriteLine($"return GetRows( {condition} ).PrimaryKeySingle({returnNullIfNoMatch});"); } }); }
private static void writeResultSetCreatorBody( DBConnection cn, TextWriter writer, IDatabase database, Table table, TableColumns tableColumns, bool tableUsesRowVersionedCaching, bool excludesPreviousRevisions, string cacheQueryInDbExpression, int?commandTimeoutSeconds) { if (tableUsesRowVersionedCaching) { writer.WriteLine("var results = new List<Row>();"); writer.WriteLine(DataAccessStatics.DataAccessStateCurrentDatabaseConnectionExpression + ".ExecuteInTransaction( () => {"); // Query for the cache keys of the results. writer.WriteLine( "var keyCommand = {0};".FormatWith( getInlineSelectExpression( table, tableColumns, "{0}, \"{1}\"".FormatWith( StringTools.ConcatenateWithDelimiter(", ", tableColumns.KeyColumns.Select(i => "\"{0}\"".FormatWith(i.Name)).ToArray()), cn.DatabaseInfo is OracleInfo ? "ORA_ROWSCN" : tableColumns.RowVersionColumn.Name), cacheQueryInDbExpression, commandTimeoutSeconds))); writer.WriteLine(getCommandConditionAddingStatement("keyCommand")); writer.WriteLine($"var keys = new List<{TypeNames.Tuple}<{getPkAndVersionTupleTypeArguments( cn, tableColumns )}>>();"); var concatenateWithDelimiter = StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select((c, i) => c.GetDataReaderValueExpression("r", ordinalOverride: i))); var o = cn.DatabaseInfo is OracleInfo ? "({0})r.GetValue( {1} )".FormatWith(oracleRowVersionDataType, tableColumns.KeyColumns.Count()) : tableColumns.RowVersionColumn.GetDataReaderValueExpression("r", ordinalOverride: tableColumns.KeyColumns.Count()); writer.WriteLine( "keyCommand.Execute( " + DataAccessStatics.DataAccessStateCurrentDatabaseConnectionExpression + ", r => { while( r.Read() ) keys.Add( " + $"{TypeNames.Tuple}.Create( {concatenateWithDelimiter}, {o} )" + " ); } );"); writer.WriteLine("var rowsByPkAndVersion = getRowsByPkAndVersion();"); writer.WriteLine("var cachedKeyCount = keys.Where( i => rowsByPkAndVersion.ContainsKey( i ) ).Count();"); // If all but a few results are cached, execute a single-row query for each missing result. writer.CodeBlock( "if( cachedKeyCount >= keys.Count() - 1 || cachedKeyCount >= keys.Count() * .99 ) {", () => { writer.WriteLine("foreach( var key in keys ) {"); writer.WriteLine("results.Add( new Row( rowsByPkAndVersion.GetOrAdd( key, () => {"); writer.WriteLine("var singleRowCommand = {0};".FormatWith(getInlineSelectExpression(table, tableColumns, "\"*\"", "false", commandTimeoutSeconds))); foreach (var i in tableColumns.KeyColumns.Select((c, i) => new { column = c, index = i })) { writer.WriteLine( $"singleRowCommand.AddCondition( ( ({table.GetTableConditionInterfaceReference()})new {table.GetEqualityConditionClassReference( cn, i.column )}( key.Item{i.index + 1} ) ).CommandCondition );"); } writer.WriteLine("var singleRowResults = new List<BasicRow>();"); writer.WriteLine( "singleRowCommand.Execute( " + DataAccessStatics.DataAccessStateCurrentDatabaseConnectionExpression + ", r => { while( r.Read() ) singleRowResults.Add( new BasicRow( r ) ); } );"); writer.WriteLine("return singleRowResults.Single();"); writer.WriteLine("} ) ) );"); writer.WriteLine("}"); }); // Otherwise, execute the full query. writer.CodeBlock( "else {", () => { writer.WriteLine( "var command = {0};".FormatWith( getInlineSelectExpression( table, tableColumns, cn.DatabaseInfo is OracleInfo ? "\"{0}.*\", \"ORA_ROWSCN\"".FormatWith(table) : "\"*\"", cacheQueryInDbExpression, commandTimeoutSeconds))); writer.WriteLine(getCommandConditionAddingStatement("command")); writer.WriteLine("command.Execute( " + DataAccessStatics.DataAccessStateCurrentDatabaseConnectionExpression + ", r => {"); writer.WriteLine( "while( r.Read() ) results.Add( new Row( rowsByPkAndVersion.GetOrAdd( System.Tuple.Create( {0}, {1} ), () => new BasicRow( r ) ) ) );".FormatWith( StringTools.ConcatenateWithDelimiter(", ", tableColumns.KeyColumns.Select(i => i.GetDataReaderValueExpression("r")).ToArray()), cn.DatabaseInfo is OracleInfo ? "({0})r.GetValue( {1} )".FormatWith(oracleRowVersionDataType, tableColumns.AllColumns.Count()) : tableColumns.RowVersionColumn.GetDataReaderValueExpression("r"))); writer.WriteLine("} );"); }); writer.WriteLine("} );"); } else { writer.WriteLine("var command = {0};".FormatWith(getInlineSelectExpression(table, tableColumns, @"""*""", cacheQueryInDbExpression, commandTimeoutSeconds))); writer.WriteLine(getCommandConditionAddingStatement("command")); writer.WriteLine("var results = new List<Row>();"); writer.WriteLine( "command.Execute( " + DataAccessStatics.DataAccessStateCurrentDatabaseConnectionExpression + ", r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } );"); } // Add all results to RowsByPk. writer.WriteLine("foreach( var i in results ) {"); var pkTupleCreationArgs = tableColumns.KeyColumns.Select(i => "i." + Utility.GetCSharpIdentifier(i.PascalCasedNameExceptForOracle)); var pkTuple = "System.Tuple.Create( " + StringTools.ConcatenateWithDelimiter(", ", pkTupleCreationArgs.ToArray()) + " )"; writer.WriteLine($"cache.RowsByPk[ {pkTuple} ] = i;"); if (excludesPreviousRevisions) { writer.WriteLine($"cache.LatestRevisionRowsByPk[ {pkTuple} ] = i;"); } writer.WriteLine("}"); writer.WriteLine("return results;"); }