private static void writeFormItemGetterWithoutValueParams(
            TextWriter writer, string controlType, ModificationField field, string controlTypeForName, bool includeValidationParams,
            IEnumerable <CSharpParameter> requiredControlParams, IEnumerable <CSharpParameter> requiredValidationParams, IEnumerable <CSharpParameter> optionalControlParams,
            IEnumerable <CSharpParameter> optionalValidationParams, IEnumerable <string> additionalSummarySentences)
        {
            // NOTE: The "out" parameter logic is a hack. We need to improve CSharpParameter.
            var body = "return " + StandardLibraryMethods.GetCSharpIdentifierSimple("Get" + field.PascalCasedName + controlTypeForName + "FormItem") + "( false, " +
                       requiredControlParams.Concat(requiredValidationParams)
                       .Select(i => (i.MethodSignatureDeclaration.StartsWith("out ") ? "out " : "") + i.Name)
                       .GetCommaDelimitedStringFromCollection()
                       .AppendDelimiter(", ") + "labelAndSubject: labelAndSubject, labelOverride: labelOverride, " +
                       optionalControlParams.Select(i => i.Name + ": " + i.Name).GetCommaDelimitedStringFromCollection().AppendDelimiter(", ") +
                       "cellSpan: cellSpan, textAlignment: textAlignment" + (includeValidationParams ? ", validationPredicate: validationPredicate" : "") +
                       optionalValidationParams.Select(i => i.Name + ": " + i.Name).GetCommaDelimitedStringFromCollection().PrependDelimiter(", ") +
                       (includeValidationParams
                                             ? ", validationErrorNotifier: validationErrorNotifier, additionalValidationMethod: additionalValidationMethod, validationList: validationList"
                                             : "") + " );";

            writeFormItemGetter(
                writer,
                controlType,
                field,
                controlTypeForName,
                "",
                requiredControlParams,
                requiredValidationParams,
                "",
                optionalControlParams,
                includeValidationParams,
                optionalValidationParams,
                body,
                additionalSummarySentences);
        }
示例#2
0
        private static void writeCreateForSingleRowUpdateMethod(
            DBConnection cn, string tableName, bool isRevisionHistoryTable, bool isRevisionHistoryClass, string methodNameSuffix)
        {
            // header
            CodeGenerationStatics.AddSummaryDocComment(
                writer,
                "Creates a modification object in single-row update mode with the specified current data. All column values in this object will have HasChanged = false, despite being initialized. This object can then be used to do a piecemeal update of the " +
                tableName + " table." );
            writer.Write(
                "public static " + GetClassName( cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass ) + " CreateForSingleRowUpdate" + methodNameSuffix + "( " );
            writeColumnParameterDeclarations( columns.AllColumnsExceptRowVersion );
            writer.WriteLine( " ) {" );

            // body

            writer.WriteLine(
                "var mod = new " + GetClassName( cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass ) + " { modType = ModificationType.Update };" );

            // Use the values of key columns as conditions.
            writer.WriteLine( "mod.conditions = new List<" + DataAccessStatics.GetTableConditionInterfaceName( cn, database, tableName ) + ">();" );
            foreach( var column in columns.KeyColumns ) {
                writer.WriteLine(
                    "mod.conditions.Add( new " + DataAccessStatics.GetEqualityConditionClassName( cn, database, tableName, column ) + "( " + "@" +
                    StandardLibraryMethods.GetCSharpIdentifierSimple( column.CamelCasedName ) + " ) );" );
            }

            writeColumnValueAssignmentsFromParameters( columns.AllColumnsExceptRowVersion, "mod" );
            writer.WriteLine( "mod.markColumnValuesUnchanged();" );
            writer.WriteLine( "return mod;" );
            writer.WriteLine( "}" );
        }
示例#3
0
        private static void writeFieldsAndPropertiesForColumn( Column column )
        {
            var columnIsReadOnly = !columns.DataColumns.Contains( column );

            writer.WriteLine(
                "private readonly DataValue<" + column.DataTypeName + "> " + getColumnFieldName( column ) + " = new DataValue<" + column.DataTypeName + ">();" );
            CodeGenerationStatics.AddSummaryDocComment(
                writer,
                "Gets " + ( columnIsReadOnly ? "" : "or sets " ) + "the value for the " + column.Name +
                " column. Throws an exception if the value has not been initialized. " + getComment( column ) );
            var propertyDeclarationBeginning = "public " + column.DataTypeName + " " +
                                               StandardLibraryMethods.GetCSharpIdentifierSimple( column.PascalCasedNameExceptForOracle ) + " { get { return " +
                                               getColumnFieldName( column ) + ".Value; } ";
            if( columnIsReadOnly )
                writer.WriteLine( propertyDeclarationBeginning + "}" );
            else {
                writer.WriteLine( propertyDeclarationBeginning + "set { " + getColumnFieldName( column ) + ".Value = value; } }" );

                CodeGenerationStatics.AddSummaryDocComment(
                    writer,
                    "Indicates whether or not the value for the " + column.Name + " has been set since object creation or the last call to Execute, whichever was latest." );
                writer.WriteLine(
                    "public bool " + StandardLibraryMethods.GetCSharpIdentifierSimple( column.PascalCasedNameExceptForOracle ) + "HasChanged { get { return " +
                    getColumnFieldName( column ) + ".Changed; } }" );
            }
        }
示例#4
0
 private static void writeColumnParameterDeclarations( IEnumerable<Column> columns )
 {
     writer.Write(
         StringTools.ConcatenateWithDelimiter(
             ", ",
             columns.Select( i => i.DataTypeName + " @" + StandardLibraryMethods.GetCSharpIdentifierSimple( i.CamelCasedName ) ).ToArray() ) );
 }
 private static void writeToIdDictionaryMethod(TextWriter writer, TableColumns tableColumns)
 {
     writer.WriteLine("public static Dictionary<" + tableColumns.KeyColumns.Single().DataTypeName + ", Row> ToIdDictionary( this IEnumerable<Row> rows ) {");
     writer.WriteLine(
         "return rows.ToDictionary( i => i." + StandardLibraryMethods.GetCSharpIdentifierSimple(tableColumns.KeyColumns.Single().PascalCasedNameExceptForOracle) +
         " );");
     writer.WriteLine("}");
 }
 private static void writeColumnProperty(TextWriter writer, Column column)
 {
     CodeGenerationStatics.AddSummaryDocComment(
         writer,
         "This object will " + (column.AllowsNull && !column.NullValueExpression.Any() ? "sometimes" : "never") + " be null.");
     writer.WriteLine(
         "public " + column.DataTypeName + " " + StandardLibraryMethods.GetCSharpIdentifierSimple(column.PascalCasedNameExceptForOracle) +
         " { get { return __basicRow." + StandardLibraryMethods.GetCSharpIdentifierSimple(column.PascalCasedName) + "; } }");
 }
示例#7
0
 private static void writeAddColumnModificationsMethod( IEnumerable<Column> nonIdentityColumns )
 {
     writer.WriteLine( "private void addColumnModifications( InlineDbModificationCommand cmd ) {" );
     foreach( var column in nonIdentityColumns ) {
         writer.WriteLine( "if( " + getColumnFieldName( column ) + ".Changed )" );
         var columnValueExpression =
             column.GetCommandColumnValueExpression( StandardLibraryMethods.GetCSharpIdentifierSimple( column.PascalCasedNameExceptForOracle ) );
         writer.WriteLine( "cmd.AddColumnModification( " + columnValueExpression + " );" );
     }
     writer.WriteLine( "}" );
 }
        private static void writeGenericGetterWithValueParams(TextWriter writer, ModificationField field, bool?includeValidationMethodReturnValue)
        {
            var control = "useValueParameter ? controlGetter( value, labelAndSubject ) : controlGetter( " +
                          StandardLibraryMethods.GetCSharpIdentifierSimple(field.PropertyName) + ", labelAndSubject )";
            var body = "return FormItem.Create( labelOverride ?? labelAndSubject, " + control + ", cellSpan: cellSpan, textAlignment: textAlignment" +
                       (includeValidationMethodReturnValue.HasValue
                                             ? ", validationGetter: " + getValidationGetter(field, includeValidationMethodReturnValue.Value)
                                             : "") + " );";

            writeGenericGetter(writer, field, true, includeValidationMethodReturnValue, body);
        }
        private static void writeGenericGetterWithoutValueParams(TextWriter writer, ModificationField field, bool?includeValidationMethodReturnValue)
        {
            var controlGetter = "( v, ls ) => controlGetter( v" + (field.TypeName != field.NullableTypeName ? ".Value" : "") + ", ls )";
            var body          = "return " + StandardLibraryMethods.GetCSharpIdentifierSimple("Get" + field.PascalCasedName + "FormItem") + "( false, " + controlGetter +
                                (includeValidationMethodReturnValue.HasValue ? ", validationMethod" : "") +
                                ", labelAndSubject: labelAndSubject, labelOverride: labelOverride, cellSpan: cellSpan, textAlignment: textAlignment" +
                                (includeValidationMethodReturnValue.HasValue
                                             ? ", validationPredicate: validationPredicate, validationErrorNotifier: validationErrorNotifier, additionalValidationMethod: additionalValidationMethod, validationList: validationList"
                                             : "") + " );";

            writeGenericGetter(writer, field, false, includeValidationMethodReturnValue, body);
        }
示例#10
0
        internal static void Generate(string rootPath, string nameSpace, TextWriter writer)
        {
            var cssClasses = new HashSet <string>();

            foreach (var fileInfo in new DirectoryInfo(rootPath).GetFiles("*.css", SearchOption.AllDirectories))
            {
                new FileReader(fileInfo.FullName).ExecuteInStreamReader(
                    delegate(StreamReader reader) {
                    // Remove comments and styles.
                    // NOTE: We need to find a way to also throw out media query expressions.
                    var text = reader.ReadToEnd().RemoveTextBetweenStrings("/*", "*/").RemoveTextBetweenStrings("{", "}");

                    foreach (Match match in Regex.Matches(text, @"\.(\w+)"))
                    {
                        cssClasses.Add(match.Groups[1].Value);
                    }
                });
            }

            if (cssClasses.Any())
            {
                writer.WriteLine("namespace " + nameSpace + " {");

                CodeGenerationStatics.AddSummaryDocComment(writer, "This class provides typesafe access to css classes present in *.css files.");
                writer.WriteLine("public class CssClasses {");

                var identifiers = new HashSet <string>();
                foreach (var cssClass in cssClasses)
                {
                    writer.WriteLine("/// <summary>");
                    writer.WriteLine("/// Constant for the '{0}' class.".FormatWith(cssClass));
                    writer.WriteLine("/// </summary>");
                    var identifier = StandardLibraryMethods.GetCSharpIdentifierSimple(cssClass).CapitalizeString();
                    if (identifiers.Contains(identifier))
                    {
                        var uniqueIdentifier = identifier;
                        var i = 0;
                        while (identifiers.Contains(uniqueIdentifier))
                        {
                            uniqueIdentifier = identifier + i++;
                        }
                        identifier = uniqueIdentifier;
                    }
                    identifiers.Add(identifier);
                    writer.WriteLine("public const string " + identifier + " = \"" + cssClass + "\";");
                }

                writer.WriteLine("}");                   // class
                writer.WriteLine("}");                   // namespace
            }
        }
        private static string getValidationGetter(ModificationField field, bool includeValidationMethodReturnValue)
        {
            var fieldPropertyName = StandardLibraryMethods.GetCSharpIdentifierSimple(field.PropertyName);
            var statements        = new[]
            {
                "if( validationPredicate != null && !validationPredicate() ) return;",
                (includeValidationMethodReturnValue ? fieldPropertyName + " = " : "") + "validationMethod( control, postBackValues, labelAndSubject, validator );",
                "if( validator.ErrorsOccurred && validationErrorNotifier != null ) validationErrorNotifier();",
                "if( !validator.ErrorsOccurred && additionalValidationMethod != null ) additionalValidationMethod( labelAndSubject, validator );"
            };

            return("control => new Validation( ( postBackValues, validator ) => { " + StringTools.ConcatenateWithDelimiter(" ", statements) +
                   " }, validationList ?? EwfPage.Instance.DataUpdate )");
        }
        private static void writeFormItemGetter(
            TextWriter writer, string controlType, ModificationField field, string controlTypeForName, string valueParamTypeName,
            IEnumerable <CSharpParameter> requiredControlParams, IEnumerable <CSharpParameter> requiredValidationParams, string valueParamDefaultValue,
            IEnumerable <CSharpParameter> optionalControlParams, bool includeValidationParams, IEnumerable <CSharpParameter> optionalValidationParams, string body,
            IEnumerable <string> additionalSummarySentences)
        {
            CodeGenerationStatics.AddSummaryDocComment(writer, getFormItemGetterSummary(field, controlTypeForName, additionalSummarySentences));
            CodeGenerationStatics.AddParamDocComment(writer, "additionalValidationMethod", "Passes the labelAndSubject and a validator to the function.");
            CodeGenerationStatics.AddParamDocComment(writer, "validationList", validationListParamDocComment);

            var parameters = new List <CSharpParameter>();

            if (valueParamTypeName.Length > 0)
            {
                parameters.Add(new CSharpParameter("bool", "useValueParameter"));
            }
            parameters.AddRange(requiredControlParams);
            parameters.AddRange(requiredValidationParams);
            parameters.Add(new CSharpParameter("string", "labelAndSubject", "\"" + getDefaultLabelAndSubject(field) + "\""));
            parameters.Add(new CSharpParameter("FormItemLabel", "labelOverride", "null"));
            if (valueParamTypeName.Length > 0)
            {
                parameters.Add(new CSharpParameter(valueParamTypeName, "value", valueParamDefaultValue));
            }
            parameters.AddRange(optionalControlParams);
            parameters.Add(new CSharpParameter("int?", "cellSpan", "null"));
            parameters.Add(new CSharpParameter("TextAlignment", "textAlignment", "TextAlignment.NotSpecified"));
            if (includeValidationParams)
            {
                parameters.Add(new CSharpParameter("System.Func<bool>", "validationPredicate", "null"));
            }
            parameters.AddRange(optionalValidationParams);
            if (includeValidationParams)
            {
                parameters.Add(new CSharpParameter("System.Action", "validationErrorNotifier", "null"));
                parameters.Add(new CSharpParameter("System.Action<string,Validator>", "additionalValidationMethod", "null"));
                parameters.Add(new CSharpParameter("ValidationList", "validationList", "null"));
            }

            writer.WriteLine(
                "public FormItem<" + controlType + "> " +
                StandardLibraryMethods.GetCSharpIdentifierSimple("Get" + field.PascalCasedName + controlTypeForName + "FormItem") + "( " +
                parameters.Select(i => i.MethodSignatureDeclaration).GetCommaDelimitedStringFromCollection() + " ) {");
            writer.WriteLine(body);
            writer.WriteLine("}");
        }
        private static void writeGenericGetter(
            TextWriter writer, ModificationField field, bool includeValueParams, bool?includeValidationMethodReturnValue, string body)
        {
            CodeGenerationStatics.AddSummaryDocComment(writer, getFormItemGetterSummary(field, "", new string[0]));
            CodeGenerationStatics.AddParamDocComment(writer, "additionalValidationMethod", "Passes the labelAndSubject and a validator to the function.");
            CodeGenerationStatics.AddParamDocComment(writer, "validationList", validationListParamDocComment);

            var parameters = new List <CSharpParameter>();

            if (includeValueParams)
            {
                parameters.Add(new CSharpParameter("bool", "useValueParameter"));
            }
            parameters.Add(
                new CSharpParameter("System.Func<" + (includeValueParams ? field.NullableTypeName : field.TypeName) + ",string,ControlType>", "controlGetter"));
            if (includeValidationMethodReturnValue.HasValue)
            {
                parameters.Add(
                    includeValidationMethodReturnValue.Value
                                                ? new CSharpParameter("System.Func<ControlType,PostBackValueDictionary,string,Validator," + field.TypeName + ">", "validationMethod")
                                                : new CSharpParameter("System.Action<ControlType,PostBackValueDictionary,string,Validator>", "validationMethod"));
            }
            parameters.Add(new CSharpParameter("string", "labelAndSubject", "\"" + getDefaultLabelAndSubject(field) + "\""));
            parameters.Add(new CSharpParameter("FormItemLabel", "labelOverride", "null"));
            if (includeValueParams)
            {
                parameters.Add(new CSharpParameter(field.NullableTypeName, "value", field.TypeIs(typeof(string)) ? "\"\"" : "null"));
            }
            parameters.Add(new CSharpParameter("int?", "cellSpan", "null"));
            parameters.Add(new CSharpParameter("TextAlignment", "textAlignment", "TextAlignment.NotSpecified"));
            if (includeValidationMethodReturnValue.HasValue)
            {
                parameters.Add(new CSharpParameter("System.Func<bool>", "validationPredicate", "null"));
                parameters.Add(new CSharpParameter("System.Action", "validationErrorNotifier", "null"));
                parameters.Add(new CSharpParameter("System.Action<string,Validator>", "additionalValidationMethod", "null"));
                parameters.Add(new CSharpParameter("ValidationList", "validationList", "null"));
            }

            writer.WriteLine(
                "public FormItem<ControlType> " + StandardLibraryMethods.GetCSharpIdentifierSimple("Get" + field.PascalCasedName + "FormItem") + "<ControlType>( " +
                parameters.Select(i => i.MethodSignatureDeclaration).GetCommaDelimitedStringFromCollection() + " ) where ControlType: Control {");
            writer.WriteLine(body);
            writer.WriteLine("}");
        }
        private static void writeFormItemGetterWithValueParams(
            TextWriter writer, string controlType, ModificationField field, string controlTypeForName, string valueParamTypeName, string valueParamDefaultValue,
            IEnumerable <CSharpParameter> requiredControlParams, IEnumerable <CSharpParameter> requiredValidationParams, IEnumerable <CSharpParameter> optionalControlParams,
            IEnumerable <CSharpParameter> optionalValidationParams, string preFormItemGetterStatements, string controlGetterExpressionOrBlock,
            string validationMethodExpressionOrBlock, string labelOverrideNullCoalescingExpression, string postFormItemGetterStatements,
            IEnumerable <string> additionalSummarySentences)
        {
            var validationMethod        = "( control, postBackValues, subject, validator ) => " + validationMethodExpressionOrBlock;
            var formItemGetterStatement = "var formItem = " + StandardLibraryMethods.GetCSharpIdentifierSimple("Get" + field.PascalCasedName + "FormItem") +
                                          "( useValueParameter, ( v, ls ) => " + controlGetterExpressionOrBlock +
                                          (validationMethodExpressionOrBlock.Any() ? ", " + validationMethod : "") +
                                          ", labelAndSubject: labelAndSubject, labelOverride: labelOverride" +
                                          labelOverrideNullCoalescingExpression.PrependDelimiter(" ?? ") +
                                          ", value: value, cellSpan: cellSpan, textAlignment: textAlignment" +
                                          (validationMethodExpressionOrBlock.Any()
                                                                ? ", validationPredicate: validationPredicate, validationErrorNotifier: validationErrorNotifier, additionalValidationMethod: additionalValidationMethod, validationList: validationList"
                                                                : "") + " );";

            writeFormItemGetter(
                writer,
                controlType,
                field,
                controlTypeForName,
                valueParamTypeName,
                requiredControlParams,
                requiredValidationParams,
                valueParamDefaultValue,
                optionalControlParams,
                validationMethodExpressionOrBlock.Any(),
                optionalValidationParams,
                StringTools.ConcatenateWithDelimiter(
                    Environment.NewLine,
                    preFormItemGetterStatements,
                    formItemGetterStatement,
                    postFormItemGetterStatements,
                    "return formItem;"),
                additionalSummarySentences);
        }
示例#15
0
        private void generateLibraryCode(DevelopmentInstallation installation)
        {
            var libraryGeneratedCodeFolderPath = StandardLibraryMethods.CombinePaths(installation.DevelopmentInstallationLogic.LibraryPath, "Generated Code");

            Directory.CreateDirectory(libraryGeneratedCodeFolderPath);
            var isuFilePath = StandardLibraryMethods.CombinePaths(libraryGeneratedCodeFolderPath, "ISU.cs");

            IoMethods.DeleteFile(isuFilePath);
            using (TextWriter writer = new StreamWriter(isuFilePath)) {
                // Don't add "using System" here. It will create a huge number of ReSharper warnings in the generated code file.
                writer.WriteLine("using System.Collections.Generic;");
                writer.WriteLine("using System.Data;");                   // Necessary for stored procedure logic
                writer.WriteLine("using System.Data.Common;");
                writer.WriteLine("using System.Diagnostics;");            // Necessary for ServerSideConsoleAppStatics
                writer.WriteLine("using System.Linq;");
                writer.WriteLine("using System.Reflection;");
                writer.WriteLine("using System.Runtime.InteropServices;");
                writer.WriteLine("using System.Web.UI;");
                writer.WriteLine("using System.Web.UI.WebControls;");
                writer.WriteLine("using RedStapler.StandardLibrary;");
                writer.WriteLine("using RedStapler.StandardLibrary.Caching;");
                writer.WriteLine("using RedStapler.StandardLibrary.Collections;");                   // Necessary for row constants
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.CommandWriting;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.CommandWriting.Commands;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.CommandWriting.InlineConditionAbstraction;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.CommandWriting.InlineConditionAbstraction.Conditions;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.RetrievalCaching;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.RevisionHistory;");
                writer.WriteLine("using RedStapler.StandardLibrary.DataAccess.StandardModification;");
                writer.WriteLine("using RedStapler.StandardLibrary.EnterpriseWebFramework;");
                writer.WriteLine("using RedStapler.StandardLibrary.EnterpriseWebFramework.Controls;");
                writer.WriteLine("using RedStapler.StandardLibrary.Validation;");

                writer.WriteLine();
                writeAssemblyInfo(writer, installation, "Library");
                writer.WriteLine();
                var recognizedInstallation = installation as RecognizedDevelopmentInstallation;
                if (ConfigurationLogic.SystemProviderExists && !installation.DevelopmentInstallationLogic.SystemIsEwl &&
                    (recognizedInstallation == null || !recognizedInstallation.SystemIsEwlCacheCoordinator))
                {
                    generateGeneralProvider(writer, installation);
                }
                if (installation.ExistingInstallationLogic.RuntimeConfiguration.WebApplications.Any())
                {
                    writer.WriteLine();
                    writer.WriteLine("namespace " + installation.DevelopmentInstallationLogic.DevelopmentConfiguration.LibraryNamespaceAndAssemblyName + " {");
                    writer.WriteLine("public static class WebApplicationNames {");
                    foreach (var i in installation.ExistingInstallationLogic.RuntimeConfiguration.WebApplications)
                    {
                        writer.WriteLine(
                            "public const string {0} = \"{1}\";".FormatWith(StandardLibraryMethods.GetCSharpIdentifierSimple(i.Name.EnglishToPascal()), i.Name));
                    }
                    writer.WriteLine("}");
                    writer.WriteLine("}");
                }
                writer.WriteLine();
                TypedCssClassStatics.Generate(
                    installation.GeneralLogic.Path,
                    installation.DevelopmentInstallationLogic.DevelopmentConfiguration.LibraryNamespaceAndAssemblyName,
                    writer);
                writer.WriteLine();
                generateServerSideConsoleAppStatics(writer, installation);
                generateDataAccessCode(writer, installation);
            }
        }
示例#16
0
 private static void writeColumnValueAssignmentsFromParameters( IEnumerable<Column> columns, string modObjectName )
 {
     foreach( var column in columns ) {
         writer.WriteLine(
             modObjectName + "." + getColumnFieldName( column ) + ".Value = @" + StandardLibraryMethods.GetCSharpIdentifierSimple( column.CamelCasedName ) + ";" );
     }
 }
示例#17
0
        private static void writeExecuteInsertOrUpdateMethod(
            DBConnection cn, string tableName, bool isRevisionHistoryClass, IEnumerable<Column> keyColumns, Column identityColumn)
        {
            writer.WriteLine( "private void executeInsertOrUpdate() {" );
            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 = (RevisionHistoryProvider)DataAccessStatics.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( "addColumnModifications( insert );" );
            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(
                            "StandardLibraryMethods.ChangeType( insert.Execute( {0} ), typeof( {1} ) )".FormatWith(
                                DataAccessStatics.GetConnectionExpression( database ),
                                identityColumn.UnconvertedDataTypeName ) ) ) );
            }
            else
                writer.WriteLine( "insert.Execute( " + 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 ) + "( " +
                    StandardLibraryMethods.GetCSharpIdentifierSimple( column.PascalCasedNameExceptForOracle ) + " ) );" );
            }

            writer.WriteLine( "}" ); // if insert

            // update
            writer.WriteLine( "else {" );
            if( isRevisionHistoryClass )
                writer.WriteLine( "copyLatestRevisions( conditions );" );
            writer.WriteLine( "var update = new InlineUpdate( \"" + tableName + "\" );" );
            writer.WriteLine( "addColumnModifications( update );" );
            writer.WriteLine( "conditions.ForEach( condition => update.AddCondition( condition.CommandCondition ) );" );
            if( isRevisionHistoryClass )
                writer.WriteLine( "update.AddCondition( getLatestRevisionsCondition() );" );
            writer.WriteLine( "update.Execute( " + DataAccessStatics.GetConnectionExpression( database ) + " );" );
            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
        }
示例#18
0
 private static string getColumnFieldName( Column column )
 {
     return StandardLibraryMethods.GetCSharpIdentifierSimple( column.CamelCasedName + "ColumnValue" );
 }
        internal static void WriteRowClasses(TextWriter writer, IEnumerable <Column> columns, Action <TextWriter> toModificationMethodWriter)
        {
            // BasicRow

            writer.WriteLine("internal class BasicRow {");
            foreach (var column in columns.Where(i => !i.IsRowVersion))
            {
                writer.WriteLine("private readonly " + column.DataTypeName + " " + getMemberVariableName(column) + ";");
            }

            writer.WriteLine("internal BasicRow( DbDataReader reader ) {");
            foreach (var column in columns.Where(i => !i.IsRowVersion))
            {
                writer.WriteLine("{0} = {1};".FormatWith(getMemberVariableName(column), column.GetDataReaderValueExpression("reader")));
            }
            writer.WriteLine("}");

            foreach (var column in columns.Where(i => !i.IsRowVersion))
            {
                writer.WriteLine(
                    "internal " + column.DataTypeName + " " + StandardLibraryMethods.GetCSharpIdentifierSimple(column.PascalCasedName) + " { get { return " +
                    getMemberVariableName(column) + "; } }");
            }

            writer.WriteLine("}");


            // Row

            CodeGenerationStatics.AddSummaryDocComment(writer, "Holds data for a row of this result.");
            writer.WriteLine("public partial class Row: System.IEquatable<Row> {");
            writer.WriteLine("private readonly BasicRow __basicRow;");

            writer.WriteLine("internal Row( BasicRow basicRow ) {");
            writer.WriteLine("__basicRow = basicRow;");
            writer.WriteLine("}");

            foreach (var column in columns.Where(i => !i.IsRowVersion))
            {
                writeColumnProperty(writer, column);
            }

            // NOTE: Being smarter about the hash code could make searches of the collection faster.
            writer.WriteLine("public override int GetHashCode() { ");
            // NOTE: Catch an exception generated by not having any uniquely identifying columns and rethrow it as a UserCorrectableException.
            writer.WriteLine(
                "return " + StandardLibraryMethods.GetCSharpIdentifierSimple(columns.First(c => c.UseToUniquelyIdentifyRow).PascalCasedNameExceptForOracle) +
                ".GetHashCode();");
            writer.WriteLine("}");               // Object override of GetHashCode

            writer.WriteLine(@"	public static bool operator == ( Row row1, Row row2 ) {
				return Equals( row1, row2 );
			}

			public static bool operator !=( Row row1, Row row2 ) {
				return !Equals( row1, row2 );
			}"            );

            writer.WriteLine("public override bool Equals( object obj ) {");
            writer.WriteLine("return Equals( obj as Row );");
            writer.WriteLine("}");               // Object override of Equals

            writer.WriteLine("public bool Equals( Row other ) {");
            writer.WriteLine("if( other == null ) return false;");

            var condition = "";

            foreach (var column in columns.Where(c => c.UseToUniquelyIdentifyRow))
            {
                condition = StringTools.ConcatenateWithDelimiter(
                    " && ",
                    condition,
                    StandardLibraryMethods.GetCSharpIdentifierSimple(column.PascalCasedNameExceptForOracle) + " == other." +
                    StandardLibraryMethods.GetCSharpIdentifierSimple(column.PascalCasedNameExceptForOracle));
            }
            writer.WriteLine("return " + condition + ";");
            writer.WriteLine("}");               // Equals method

            toModificationMethodWriter(writer);

            writer.WriteLine("}");               // class
        }
 private static string getMemberVariableName(Column column)
 {
     // A single underscore is a pretty common thing for other code generators and even some developers to use, so two is more unique and avoids problems.
     return(StandardLibraryMethods.GetCSharpIdentifierSimple("__" + column.CamelCasedName));
 }
        internal static void Generate(
            DBConnection cn, TextWriter writer, string namespaceDeclaration, Database database,
            RedStapler.StandardLibrary.Configuration.SystemDevelopment.Database configuration)
        {
            writer.WriteLine(namespaceDeclaration);
            foreach (var table in DatabaseOps.GetDatabaseTables(database))
            {
                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 (!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 => StandardLibraryMethods.GetCSharpIdentifierSimple(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);
                }

                if (columns.KeyColumns.Count() == 1 && columns.KeyColumns.Single().Name.ToLower().EndsWith("id"))
                {
                    writeGetRowMatchingIdMethod(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);
                }

                writer.WriteLine("}");           // class
            }
            writer.WriteLine("}");               // namespace
        }
        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." + StandardLibraryMethods.GetCSharpIdentifierSimple(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;");
        }