private static void writeExecuteMethod(string tableName) { CodeGenerationStatics.AddSummaryDocComment( writer, "Executes this " + tableName + " modification, persisting all changes. Executes any pre-insert, pre-update, post-insert, or post-update logic that may exist in the class."); writer.WriteLine("public void Execute( bool isLongRunning = false ) {"); writer.WriteLine(DataAccessStatics.GetConnectionExpression(database) + ".ExecuteInTransaction( delegate {"); // The mod type may change during execute. writer.WriteLine("var frozenModType = modType;"); writer.WriteLine("if( frozenModType == ModificationType.Insert )"); writer.WriteLine("preInsert();"); writer.WriteLine("else if( frozenModType == ModificationType.Update )"); writer.WriteLine("preUpdate();"); writer.WriteLine("executeInsertOrUpdate( isLongRunning );"); writer.WriteLine("if( frozenModType == ModificationType.Insert )"); writer.WriteLine("postInsert();"); writer.WriteLine("else if( frozenModType == ModificationType.Update )"); writer.WriteLine("postUpdate();"); // This must be after the calls to postInsert and postUpdate in case their implementations need to know which column values changed. writer.WriteLine("markColumnValuesUnchanged();"); writer.WriteLine("} );"); writer.WriteLine("}"); }
private static void writeQueryMethod( TextWriter writer, Database database, EnterpriseWebLibrary.Configuration.SystemDevelopment.Query query, EnterpriseWebLibrary.Configuration.SystemDevelopment.QueryPostSelectFromClause postSelectFromClause) { // header CodeGenerationStatics.AddSummaryDocComment(writer, "Queries the database and returns the full results collection immediately."); writer.WriteLine( "public static IEnumerable<Row> GetRows" + postSelectFromClause.name + "( " + DataAccessStatics.GetMethodParamsFromCommandText(info, query.selectFromClause + " " + postSelectFromClause.Value) + " ) {"); // body var namedParamList = DataAccessStatics.GetNamedParamList(info, query.selectFromClause + " " + postSelectFromClause.Value); var getResultSetFirstArg = namedParamList.Any() ? "new[] { " + StringTools.ConcatenateWithDelimiter(", ", namedParamList.ToArray()) + " }, " : ""; writer.WriteLine("return Cache.Current." + getQueryCacheName(query, postSelectFromClause) + ".GetResultSet( " + getResultSetFirstArg + "() => {"); writer.WriteLine("var cmd = " + DataAccessStatics.GetConnectionExpression(database) + ".DatabaseInfo.CreateCommand();"); writer.WriteLine("cmd.CommandText = selectFromClause + @\"" + postSelectFromClause.Value + "\";"); DataAccessStatics.WriteAddParamBlockFromCommandText(writer, "cmd", info, query.selectFromClause + " " + postSelectFromClause.Value, database); writer.WriteLine("var results = new List<Row>();"); writer.WriteLine( DataAccessStatics.GetConnectionExpression(database) + ".ExecuteReaderCommand( cmd, r => { while( r.Read() ) results.Add( new Row( new BasicRow( r ) ) ); } );"); // Update single-row caches. writer.WriteLine("foreach( var i in results )"); writer.WriteLine("updateSingleRowCaches( i );"); writer.WriteLine("return results;"); writer.WriteLine("} );"); writer.WriteLine("}"); }
internal static void Generate(DBConnection cn, TextWriter writer, string baseNamespace, Database database) { writer.WriteLine("namespace " + baseNamespace + "." + database.SecondaryDatabaseName + "Sequences {"); var cmd = cn.DatabaseInfo.CreateCommand(); cmd.CommandText = "SELECT * FROM USER_SEQUENCES"; cn.ExecuteReaderCommand(cmd, reader => { while (reader.Read()) { var sequenceName = reader["SEQUENCE_NAME"].ToString(); writer.WriteLine(); writer.WriteLine("public class " + sequenceName + " {"); writer.WriteLine("public static decimal GetNextValue() {"); writer.WriteLine("DbCommand cmd = " + DataAccessStatics.GetConnectionExpression(database) + ".DatabaseInfo.CreateCommand();"); writer.WriteLine("cmd.CommandText = \"SELECT " + sequenceName + ".NEXTVAL FROM DUAL\";"); writer.WriteLine("return (decimal)" + DataAccessStatics.GetConnectionExpression(database) + ".ExecuteScalarCommand( cmd );"); writer.WriteLine("}"); writer.WriteLine("}"); } }); writer.WriteLine(); writer.WriteLine("}"); }
private static void writePrivateDeleteRowsMethod( DBConnection cn, string tableName, bool isRevisionHistoryClass ) { // NOTE: For revision history tables, we should have the delete method automatically clean up the revisions table (but not user transactions) for us when doing direct-with-revision-bypass deletions. writer.WriteLine( "private static int deleteRows( List<" + DataAccessStatics.GetTableConditionInterfaceName( cn, database, tableName ) + "> conditions ) {" ); if( isRevisionHistoryClass ) writer.WriteLine( "return " + DataAccessStatics.GetConnectionExpression( database ) + ".ExecuteInTransaction( () => {" ); if( isRevisionHistoryClass ) writer.WriteLine( "copyLatestRevisions( conditions );" ); writer.WriteLine( "var delete = new InlineDelete( \"" + tableName + "\" );" ); writer.WriteLine( "conditions.ForEach( condition => delete.AddCondition( condition.CommandCondition ) );" ); if( isRevisionHistoryClass ) writer.WriteLine( "delete.AddCondition( getLatestRevisionsCondition() );" ); writer.WriteLine( "try {" ); writer.WriteLine( "return delete.Execute( " + DataAccessStatics.GetConnectionExpression( database ) + " );" ); writer.WriteLine( "}" ); // try writer.WriteLine( "catch( System.Exception e ) {" ); writer.WriteLine( "rethrowAsDataModificationExceptionIfNecessary( e );" ); writer.WriteLine( "throw;" ); writer.WriteLine( "}" ); // catch if( isRevisionHistoryClass ) writer.WriteLine( "} );" ); // cn.ExecuteInTransaction writer.WriteLine( "}" ); }
private static void writeDeleteRowsMethod( DBConnection cn, string tableName, string methodNameSuffix, bool executeAdditionalLogic ) { CodeGenerationStatics.AddSummaryDocComment( writer, "<para>Deletes the rows that match the specified conditions and returns the number of rows deleted.</para>" + "<para>WARNING: After calling this method, delete referenced rows in other tables that are no longer needed.</para>" ); writer.WriteLine( "public static int DeleteRows" + methodNameSuffix + "( " + getConditionParameterDeclarations( cn, tableName ) + " ) {" ); if( executeAdditionalLogic ) writer.WriteLine( "return " + DataAccessStatics.GetConnectionExpression( database ) + ".ExecuteInTransaction( () => {" ); writer.WriteLine( "var conditions = getConditionList( requiredCondition, additionalConditions );" ); if( executeAdditionalLogic ) { writer.WriteLine( getPostDeleteCallClassName( cn, tableName ) + " postDeleteCall = null;" ); writer.WriteLine( "preDelete( conditions, ref postDeleteCall );" ); } writer.WriteLine( "var rowsDeleted = deleteRows( conditions );" ); if( executeAdditionalLogic ) { writer.WriteLine( "if( postDeleteCall != null )" ); writer.WriteLine( "postDeleteCall.Execute();" ); } writer.WriteLine( "return rowsDeleted;" ); if( executeAdditionalLogic ) writer.WriteLine( "} );" ); // cn.ExecuteInTransaction writer.WriteLine( "}" ); }
private static void writeCopyLatestRevisionsMethod( DBConnection cn, string tableName, IEnumerable<Column> nonIdentityColumns ) { writer.WriteLine( "private static void copyLatestRevisions( List<" + DataAccessStatics.GetTableConditionInterfaceName( cn, database, tableName ) + "> conditions ) {" ); writer.WriteLine( "var revisionHistorySetup = (RevisionHistoryProvider)DataAccessStatics.SystemProvider;" ); writer.WriteLine( "var command = new InlineSelect( \"" + columns.PrimaryKeyAndRevisionIdColumn.Name + "\".ToSingleElementArray(), \"FROM " + tableName + "\", false );" ); writer.WriteLine( "conditions.ForEach( condition => command.AddCondition( condition.CommandCondition ) );" ); writer.WriteLine( "command.AddCondition( getLatestRevisionsCondition() );" ); writer.WriteLine( "var latestRevisionIds = new List<int>();" ); writer.WriteLine( "command.Execute( " + DataAccessStatics.GetConnectionExpression( database ) + ", r => { while( r.Read() ) latestRevisionIds.Add( System.Convert.ToInt32( r[0] ) ); } );" ); writer.WriteLine( "foreach( var latestRevisionId in latestRevisionIds ) {" ); // Get the latest revision. writer.WriteLine( "var latestRevision = revisionHistorySetup.GetRevision( latestRevisionId );" ); // If this condition is true, we've already modified the row in this transaction. If we were to copy it, we'd end up with two revisions of the same entity // in the same user transaction, which we don't support. writer.WriteLine( "if( latestRevision.UserTransactionId == " + DataAccessStatics.GetConnectionExpression( database ) + ".GetUserTransactionId() )" ); writer.WriteLine( "continue;" ); // Update the latest revision with a new user transaction. writer.WriteLine( "revisionHistorySetup.UpdateRevision( latestRevisionId, latestRevisionId, " + DataAccessStatics.GetConnectionExpression( database ) + ".GetUserTransactionId(), latestRevisionId );" ); // Insert a copy of the latest revision with a new ID. This will represent the revision of the data before it was changed. writer.WriteLine( "var copiedRevisionId = revisionHistorySetup.GetNextMainSequenceValue();" ); writer.WriteLine( "revisionHistorySetup.InsertRevision( copiedRevisionId, latestRevisionId, latestRevision.UserTransactionId );" ); // Insert a copy of the data row and make it correspond to the copy of the latest revision. writer.WriteLine( "var copyCommand = " + DataAccessStatics.GetConnectionExpression( database ) + ".DatabaseInfo.CreateCommand();" ); writer.WriteLine( "copyCommand.CommandText = \"INSERT INTO " + tableName + " SELECT \";" ); foreach( var column in nonIdentityColumns ) { if( column == columns.PrimaryKeyAndRevisionIdColumn ) { writer.WriteLine( "var revisionIdParameter = new DbCommandParameter( \"copiedRevisionId\", new DbParameterValue( copiedRevisionId ) );" ); writer.WriteLine( "copyCommand.CommandText += revisionIdParameter.GetNameForCommandText( " + DataAccessStatics.GetConnectionExpression( database ) + ".DatabaseInfo ) + \", \";" ); writer.WriteLine( "copyCommand.Parameters.Add( revisionIdParameter.GetAdoDotNetParameter( " + DataAccessStatics.GetConnectionExpression( database ) + ".DatabaseInfo ) );" ); } else writer.WriteLine( "copyCommand.CommandText += \"" + column.Name + ", \";" ); } writer.WriteLine( "copyCommand.CommandText = copyCommand.CommandText.Remove( copyCommand.CommandText.Length - 2 );" ); writer.WriteLine( "copyCommand.CommandText += \" FROM " + tableName + " WHERE \";" ); writer.WriteLine( "( new EqualityCondition( new InlineDbCommandColumnValue( \"" + columns.PrimaryKeyAndRevisionIdColumn.Name + "\", new DbParameterValue( latestRevisionId ) ) ) as InlineDbCommandCondition ).AddToCommand( copyCommand, " + DataAccessStatics.GetConnectionExpression( database ) + ".DatabaseInfo, \"latestRevisionId\" );" ); writer.WriteLine( DataAccessStatics.GetConnectionExpression( database ) + ".ExecuteNonQueryCommand( copyCommand );" ); writer.WriteLine( "}" ); // foreach writer.WriteLine( "}" ); // method }
private static void writeDeleteRowsMethod( DBConnection cn, string tableName, string methodNameSuffix, bool includeIsLongRunningParameter, bool executeAdditionalLogic) { CodeGenerationStatics.AddSummaryDocComment( writer, "<para>Deletes the rows that match the specified conditions and returns the number of rows deleted.</para>" + "<para>WARNING: After calling this method, delete referenced rows in other tables that are no longer needed.</para>"); writer.WriteLine( "public static int DeleteRows{0}( {1} ) {{".FormatWith( methodNameSuffix, StringTools.ConcatenateWithDelimiter( ", ", includeIsLongRunningParameter ? "bool isLongRunning" : "", getConditionParameterDeclarations(cn, tableName)))); if (executeAdditionalLogic) { writer.WriteLine("return " + DataAccessStatics.GetConnectionExpression(database) + ".ExecuteInTransaction( () => {"); } writer.WriteLine("var conditions = getConditionList( requiredCondition, additionalConditions );"); if (executeAdditionalLogic) { writer.WriteLine(getPostDeleteCallClassName(cn, tableName) + " postDeleteCall = null;"); writer.WriteLine("preDelete( conditions, ref postDeleteCall );"); } writer.WriteLine("var rowsDeleted = deleteRows( conditions, {0} );".FormatWith(includeIsLongRunningParameter ? "isLongRunning" : "false")); if (executeAdditionalLogic) { writer.WriteLine("if( postDeleteCall != null )"); writer.WriteLine("postDeleteCall.Execute();"); } writer.WriteLine("return rowsDeleted;"); if (executeAdditionalLogic) { writer.WriteLine("} );"); // cn.ExecuteInTransaction } writer.WriteLine("}"); }
private static void writeMethod(TextWriter writer, Database database, RedStapler.StandardLibrary.Configuration.SystemDevelopment.CustomModification mod) { writer.WriteLine("public static void " + mod.name + "( " + DataAccessStatics.GetMethodParamsFromCommandText(info, StringTools.ConcatenateWithDelimiter("; ", mod.commands)) + " ) {"); writer.WriteLine(DataAccessStatics.GetConnectionExpression(database) + ".ExecuteInTransaction( delegate {"); var cnt = 0; foreach (var command in mod.commands) { var commandVariableName = "cmd" + cnt++; writer.WriteLine("DbCommand " + commandVariableName + " = " + DataAccessStatics.GetConnectionExpression(database) + ".DatabaseInfo.CreateCommand();"); writer.WriteLine(commandVariableName + ".CommandText = @\"" + command + "\";"); DataAccessStatics.WriteAddParamBlockFromCommandText(writer, commandVariableName, info, command, database); writer.WriteLine(DataAccessStatics.GetConnectionExpression(database) + ".ExecuteNonQueryCommand( " + commandVariableName + " );"); } writer.WriteLine("} );"); // execute in transaction call writer.WriteLine("}"); // method }
private static void writeExecuteInsertOrUpdateMethod( DBConnection cn, string tableName, bool isRevisionHistoryClass, IEnumerable <Column> keyColumns, Column identityColumn) { writer.WriteLine("private void executeInsertOrUpdate( bool isLongRunning ) {"); writer.WriteLine("try {"); if (isRevisionHistoryClass) { writer.WriteLine(DataAccessStatics.GetConnectionExpression(database) + ".ExecuteInTransaction( delegate {"); } // insert writer.WriteLine("if( modType == ModificationType.Insert ) {"); // If this is a revision history table, write code to insert a new revision when a row is inserted into this table. if (isRevisionHistoryClass) { writer.WriteLine("var revisionHistorySetup = RevisionHistoryStatics.SystemProvider;"); writer.WriteLine(getColumnFieldName(columns.PrimaryKeyAndRevisionIdColumn) + ".Value = revisionHistorySetup.GetNextMainSequenceValue();"); writer.WriteLine( "revisionHistorySetup.InsertRevision( System.Convert.ToInt32( " + getColumnFieldName(columns.PrimaryKeyAndRevisionIdColumn) + ".Value ), System.Convert.ToInt32( " + getColumnFieldName(columns.PrimaryKeyAndRevisionIdColumn) + ".Value ), " + DataAccessStatics.GetConnectionExpression(database) + ".GetUserTransactionId() );"); } writer.WriteLine("var insert = new InlineInsert( \"" + tableName + "\" );"); writer.WriteLine("insert.AddColumnModifications( getColumnModificationValues() );"); if (identityColumn != null) { // One reason the ChangeType call is necessary: SQL Server identities always come back as decimal, and you can't cast a boxed decimal to an int. writer.WriteLine( "{0}.Value = {1};".FormatWith( getColumnFieldName(identityColumn), identityColumn.GetIncomingValueConversionExpression( "EwlStatics.ChangeType( insert.Execute( {0}, isLongRunning: isLongRunning ), typeof( {1} ) )".FormatWith( DataAccessStatics.GetConnectionExpression(database), identityColumn.UnconvertedDataTypeName)))); } else { writer.WriteLine("insert.Execute( {0}, isLongRunning: isLongRunning );".FormatWith(DataAccessStatics.GetConnectionExpression(database))); } // Future calls to Execute should perform updates, not inserts. Use the values of key columns as conditions. writer.WriteLine("modType = ModificationType.Update;"); writer.WriteLine("conditions = new List<" + DataAccessStatics.GetTableConditionInterfaceName(cn, database, tableName) + ">();"); foreach (var column in keyColumns) { writer.WriteLine( "conditions.Add( new " + DataAccessStatics.GetEqualityConditionClassName(cn, database, tableName, column) + "( " + EwlStatics.GetCSharpIdentifier(column.PascalCasedNameExceptForOracle) + " ) );"); } writer.WriteLine("}"); // if insert // update writer.WriteLine("else {"); writer.WriteLine("var modificationValues = getColumnModificationValues();"); writer.WriteLine("if( modificationValues.Any() ) {"); if (isRevisionHistoryClass) { writer.WriteLine("copyLatestRevisions( conditions, isLongRunning );"); } writer.WriteLine("var update = new InlineUpdate( \"" + tableName + "\" );"); writer.WriteLine("update.AddColumnModifications( modificationValues );"); writer.WriteLine("conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) );"); if (isRevisionHistoryClass) { writer.WriteLine("update.AddCondition( getLatestRevisionsCondition() );"); } writer.WriteLine("update.Execute( {0}, isLongRunning: isLongRunning );".FormatWith(DataAccessStatics.GetConnectionExpression(database))); writer.WriteLine("}"); writer.WriteLine("}"); // else if (isRevisionHistoryClass) { writer.WriteLine("} );"); // cn.ExecuteInTransaction } writer.WriteLine("}"); // try writer.WriteLine("catch( System.Exception e ) {"); writer.WriteLine("rethrowAsDataModificationExceptionIfNecessary( e );"); writer.WriteLine("throw;"); writer.WriteLine("}"); // catch writer.WriteLine("}"); // method }
private static void writeResultSetCreatorBody( DBConnection cn, TextWriter writer, Database database, string table, TableColumns tableColumns, bool tableUsesRowVersionedCaching, bool excludesPreviousRevisions, string cacheQueryInDbExpression) { if (tableUsesRowVersionedCaching) { writer.WriteLine("var results = new List<Row>();"); writer.WriteLine(DataAccessStatics.GetConnectionExpression(database) + ".ExecuteInTransaction( delegate {"); // 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))); writer.WriteLine(getCommandConditionAddingStatement("keyCommand")); writer.WriteLine("var keys = new List<System.Tuple<{0}>>();".FormatWith(getPkAndVersionTupleTypeArguments(cn, tableColumns))); writer.WriteLine( "keyCommand.Execute( " + DataAccessStatics.GetConnectionExpression(database) + ", r => { while( r.Read() ) keys.Add( " + "System.Tuple.Create( {0}, {1} )".FormatWith( StringTools.ConcatenateWithDelimiter( ", ", tableColumns.KeyColumns.Select((c, i) => c.GetDataReaderValueExpression("r", ordinalOverride: i)).ToArray()), cn.DatabaseInfo is OracleInfo ? "({0})r.GetValue( {1} )".FormatWith(oracleRowVersionDataType, tableColumns.KeyColumns.Count()) : tableColumns.RowVersionColumn.GetDataReaderValueExpression("r", ordinalOverride: tableColumns.KeyColumns.Count())) + " ); } );"); 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.WriteLine("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"))); foreach (var i in tableColumns.KeyColumns.Select((c, i) => new { column = c, index = i })) { writer.WriteLine( "singleRowCommand.AddCondition( ( ({0})new {1}( key.Item{2} ) ).CommandCondition );".FormatWith( DataAccessStatics.GetTableConditionInterfaceName(cn, database, table), DataAccessStatics.GetEqualityConditionClassName(cn, database, table, i.column), i.index + 1)); } writer.WriteLine("var singleRowResults = new List<BasicRow>();"); writer.WriteLine( "singleRowCommand.Execute( " + DataAccessStatics.GetConnectionExpression(database) + ", r => { while( r.Read() ) singleRowResults.Add( new BasicRow( r ) ); } );"); writer.WriteLine("return singleRowResults.Single();"); writer.WriteLine("} ) ) );"); writer.WriteLine("}"); writer.WriteLine("}"); // Otherwise, execute the full query. writer.WriteLine("else {"); writer.WriteLine( "var command = {0};".FormatWith( getInlineSelectExpression( table, tableColumns, cn.DatabaseInfo is OracleInfo ? "\"{0}.*\", \"ORA_ROWSCN\"".FormatWith(table) : "\"*\"", cacheQueryInDbExpression))); writer.WriteLine(getCommandConditionAddingStatement("command")); writer.WriteLine("command.Execute( " + DataAccessStatics.GetConnectionExpression(database) + ", 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("}"); writer.WriteLine("} );"); } else { writer.WriteLine("var command = {0};".FormatWith(getInlineSelectExpression(table, tableColumns, "\"*\"", cacheQueryInDbExpression))); writer.WriteLine(getCommandConditionAddingStatement("command")); writer.WriteLine("var results = new List<Row>();"); writer.WriteLine( "command.Execute( " + DataAccessStatics.GetConnectionExpression(database) + ", 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." + EwlStatics.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;"); }
internal static void Generate(DBConnection cn, TextWriter writer, string baseNamespace, Database database) { writer.WriteLine("namespace " + baseNamespace + " {"); writer.WriteLine("public static class " + database.SecondaryDatabaseName + "Procedures {"); foreach (var procedure in database.GetProcedures()) { var parameters = database.GetProcedureParameters(procedure); // header CodeGenerationStatics.AddSummaryDocComment(writer, "Executes the " + procedure + " procedure."); var parameterDeclarations = parameters.Select( i => (i.Direction == ParameterDirection.Output ? "out " : i.Direction == ParameterDirection.InputOutput ? "ref " : "") + i.DataTypeName + " " + i.Name); writer.WriteLine("public static void " + procedure + "( " + StringTools.ConcatenateWithDelimiter(", ", parameterDeclarations.ToArray()) + " ) {"); // body writer.WriteLine("var cmd = new SprocExecution( \"" + procedure + "\" );"); foreach (var parameter in parameters) { if (parameter.Direction == ParameterDirection.Input) { writer.WriteLine("cmd.AddParameter( " + getDbCommandParameterCreationExpression(parameter) + " );"); } else { writer.WriteLine("var " + parameter.Name + "Parameter = " + getDbCommandParameterCreationExpression(parameter) + ";"); writer.WriteLine( parameter.Name + "Parameter.GetAdoDotNetParameter( " + DataAccessStatics.GetConnectionExpression(database) + ".DatabaseInfo ).Direction = ParameterDirection." + parameter.Direction + ";"); writer.WriteLine("cmd.AddParameter( " + parameter.Name + "Parameter );"); } } foreach (var parameter in parameters.Where(parameter => parameter.Direction != ParameterDirection.Input)) { writer.WriteLine(parameter.DataTypeName + " " + parameter.Name + "Local = default( " + parameter.DataTypeName + " );"); } writer.WriteLine("cmd.ExecuteReader( " + DataAccessStatics.GetConnectionExpression(database) + ", r => {"); foreach (var parameter in parameters.Where(parameter => parameter.Direction != ParameterDirection.Input)) { var adoDotNetParameterValueExpression = "{0}Parameter.GetAdoDotNetParameter( {1}.DatabaseInfo ).Value".FormatWith( parameter.Name, DataAccessStatics.GetConnectionExpression(database)); // We are not sure if this is handling null correctly. When a null comes back via an "out" parameter, we're not sure whether it is represented with // DBNull.Value or in another way. This issue can be resolved as soon as we have a system with stored procedures that we can use for testing. // NOTE: This is a hack. We would like to use a simple cast to convert the value of the database parameter to the method parameter's type, but we // can't because the types in Oracle.DataAccess.Types, like OracleDecimal, do not support any kind of conversion to .NET types when they are boxed. writer.WriteLine( "{0}Local = {1};".FormatWith( parameter.Name, parameter.GetIncomingValueConversionExpression( "EwlStatics.ChangeType( {0}.ToString(), typeof( {1} ) )".FormatWith( adoDotNetParameterValueExpression, parameter.UnconvertedDataTypeName)))); //writer.WriteLine( "{0}Local = {1};".FormatWith( parameter.Name, parameter.GetIncomingValueConversionExpression( adoDotNetParameterValueExpression ) ) ); } writer.WriteLine("} );"); foreach (var parameter in parameters.Where(parameter => parameter.Direction != ParameterDirection.Input)) { writer.WriteLine(parameter.Name + " = " + parameter.Name + "Local;"); } writer.WriteLine("}"); } writer.WriteLine("}"); writer.WriteLine("}"); }