Exemple #1
0
        internal static void Generate(
            DBConnection cn, TextWriter writer, string namespaceDeclaration, Database database, 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 (!isRevisionHistoryTable)
                    {
                        return;
                    }
                    writer.WriteLine(
                        "public UserTransaction Transaction { get { return RevisionHistoryStatics.UserTransactionsById[ RevisionHistoryStatics.RevisionsById[ System.Convert.ToInt32( " +
                        EwlStatics.GetCSharpIdentifierSimple(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.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);
                }

                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);
                }

                writer.WriteLine("}");           // class
            }
            writer.WriteLine("}");               // namespace
        }
Exemple #2
0
        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.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;");
        }
        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("}");
        }
        /// <summary>
        /// Initializes the system. This includes loading application settings from the configuration file. The application name should be scoped within the system.
        /// For non web applications, this method must be called directly from the main executable assembly and not from a supporting library.
        ///
        /// To debug this method, create a folder called C:\AnyoneFullControl and give Everyone full control. A file will appear in that folder explaining how far
        /// it got in init.
        /// </summary>
        /// <param name="globalInitializer">The system's global initializer. Do not pass null.</param>
        /// <param name="appName"></param>
        /// <param name="isClientSideProgram"></param>
        /// <param name="useRelativeInstallationPath">Pass true to use a relative path for the installation folder. This means that the folder will be located using
        /// the working directory rather than the assembly path. Use with caution.</param>
        /// <param name="mainDataAccessStateGetter">A method that returns the current main data-access state whenever it is requested, including during this
        /// InitStatics call. Do not allow multiple threads to use the same state at the same time. If you pass null, the data-access subsystem will not be
        /// available in the application.</param>
        public static void InitStatics(
            SystemInitializer globalInitializer, string appName, bool isClientSideProgram, bool useRelativeInstallationPath = false,
            Func <DataAccessState> mainDataAccessStateGetter = null)
        {
            var initializationLog = "Starting init";

            try {
                if (initialized)
                {
                    throw new ApplicationException("This class can only be initialized once.");
                }

                if (globalInitializer == null)
                {
                    throw new ApplicationException("The system must have a global initializer.");
                }

                // Initialize ConfigurationStatics, including the general provider, before the exception handling block below because it's reasonable for the exception
                // handling to depend on this.
                ConfigurationStatics.Init(useRelativeInstallationPath, globalInitializer.GetType(), appName, isClientSideProgram, ref initializationLog);

                // Setting the initialized flag to true must be done before executing the secondary init block below so that exception handling works.
                initialized        = true;
                initializationLog += Environment.NewLine + "Succeeded in primary init.";
            }
            catch (Exception e) {
                initializationLog += Environment.NewLine + e;
                EwlStatics.EmergencyLog("Initialization log", initializationLog);
                throw;
            }

            try {
                var asposeLicense = ConfigurationStatics.SystemGeneralProvider.AsposeLicenseName;
                if (asposeLicense.Any())
                {
                    new Aspose.Pdf.License().SetLicense(asposeLicense);
                    new Aspose.Words.License().SetLicense(asposeLicense);
                }

                AppMemoryCache.Init();
                BlobFileOps.Init();
                DataAccessStatics.Init();
                DataAccessState.Init(mainDataAccessStateGetter);
                EmailStatics.Init();
                EncryptionOps.Init();
                HtmlBlockStatics.Init();
                InstallationSupportUtility.ConfigurationLogic.Init1();
                UserManagementStatics.Init();

                GlobalInitializationOps.globalInitializer = globalInitializer;
                globalInitializer.InitStatics();
            }
            catch (Exception e) {
                secondaryInitFailed = true;

                // Suppress all exceptions since they would prevent apps from knowing that primary initialization succeeded. EWF apps need to know this in order to
                // automatically restart themselves. Other apps could find this knowledge useful as well.
                try {
                    TelemetryStatics.ReportError("An exception occurred during application initialization:", e);
                }
                catch {}
            }
        }
 private static string getQueryCacheName(
     Configuration.SystemDevelopment.Query query, Configuration.SystemDevelopment.QueryPostSelectFromClause postSelectFromClause, bool getFieldName)
 {
     return((getFieldName ? "rows" : "Rows") + postSelectFromClause.name +
            (DataAccessStatics.GetNamedParamList(info, query.selectFromClause + " " + postSelectFromClause.Value).Any() ? "Queries" : "Query"));
 }
Exemple #6
0
        /// <summary>
        /// Initializes the system. This includes loading application settings from the configuration file. The application name should be scoped within the system.
        /// For non web applications, this method must be called directly from the main executable assembly and not from a supporting library.
        ///
        /// To debug this method, create a folder called C:\AnyoneFullControl and give Everyone full control. A file will appear in that folder explaining how far
        /// it got in init.
        /// </summary>
        /// <param name="globalInitializer">The system's global initializer. Do not pass null.</param>
        /// <param name="appName"></param>
        /// <param name="isClientSideApp"></param>
        /// <param name="assemblyFolderPath">Pass a nonempty string to override the assembly folder path, which is used to locate the installation folder. Use with
        /// caution.</param>
        /// <param name="mainDataAccessStateGetter">A method that returns the current main data-access state whenever it is requested, including during this
        /// InitStatics call. Do not allow multiple threads to use the same state at the same time. If you pass null, the data-access subsystem will not be
        /// available in the application.</param>
        /// <param name="useLongDatabaseTimeouts">Pass true if the application is a background process that can tolerate slow database access.</param>
        public static void InitStatics(
            SystemInitializer globalInitializer, string appName, bool isClientSideApp, string assemblyFolderPath = "",
            Func <DataAccessState> mainDataAccessStateGetter = null, bool useLongDatabaseTimeouts = false)
        {
            var initializationLog = "Starting init";

            try {
                if (initialized)
                {
                    throw new ApplicationException("This class can only be initialized once.");
                }

                if (globalInitializer == null)
                {
                    throw new ApplicationException("The system must have a global initializer.");
                }

                // Initialize these before the exception handling block below because it's reasonable for the exception handling to depend on them.
                ConfigurationStatics.Init(assemblyFolderPath, globalInitializer.GetType(), appName, isClientSideApp, ref initializationLog);
                EmailStatics.Init();
                TelemetryStatics.Init();

                // Setting the initialized flag to true must be done before executing the secondary init block below so that exception handling works.
                initialized        = true;
                initializationLog += Environment.NewLine + "Succeeded in primary init.";
            }
            catch (Exception e) {
                initializationLog += Environment.NewLine + e;
                EwlStatics.EmergencyLog("Initialization log", initializationLog);
                throw;
            }

            try {
                CultureInfo.DefaultThreadCurrentCulture = Cultures.EnglishUnitedStates;

                JsonConvert.DefaultSettings = () => new JsonSerializerSettings().ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);

                var asposePdfLicensePath = EwlStatics.CombinePaths(ConfigurationStatics.InstallationConfiguration.AsposeLicenseFolderPath, "Aspose.PDF.lic");
                if (File.Exists(asposePdfLicensePath))
                {
                    new Aspose.Pdf.License().SetLicense(asposePdfLicensePath);
                }
                var asposeWordsLicensePath = EwlStatics.CombinePaths(ConfigurationStatics.InstallationConfiguration.AsposeLicenseFolderPath, "Aspose.Words.lic");
                if (File.Exists(asposeWordsLicensePath))
                {
                    new Aspose.Words.License().SetLicense(asposeWordsLicensePath);
                }

                AppMemoryCache.Init();
                BlobStorageStatics.Init();
                DataAccessStatics.Init();
                DataAccessState.Init(mainDataAccessStateGetter, useLongDatabaseTimeouts);
                EncryptionOps.Init();
                HtmlBlockStatics.Init();
                UserManagementStatics.Init(
                    () => {
                    if (ExternalFunctionalityStatics.SamlFunctionalityEnabled)
                    {
                        ExternalFunctionalityStatics.ExternalSamlProvider.RefreshConfiguration();
                    }
                });

                ExternalFunctionalityStatics.Init();

                GlobalInitializationOps.globalInitializer = globalInitializer;
                globalInitializer.InitStatics();

                UserManagementStatics.InitSystemSpecificLogicDependencies();
            }
            catch (Exception e) {
                secondaryInitFailed = true;

                // Suppress all exceptions since they would prevent apps from knowing that primary initialization succeeded. EWF apps need to know this in order to
                // automatically restart themselves. Other apps could find this knowledge useful as well.
                try {
                    TelemetryStatics.ReportError("An exception occurred during application initialization:", e);
                }
                catch {}
            }
        }
Exemple #7
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
        }
Exemple #8
0
 private static string getConditionParameterDeclarations( DBConnection cn, string tableName )
 {
     return "" + DataAccessStatics.GetTableConditionInterfaceName( cn, database, tableName ) + " requiredCondition, params " +
            DataAccessStatics.GetTableConditionInterfaceName( cn, database, tableName ) + "[] additionalConditions";
 }
Exemple #9
0
        private static void writeCreateForUpdateMethod(
            DBConnection cn, string tableName, bool isRevisionHistoryTable, bool isRevisionHistoryClass, string methodNameSuffix)
        {
            // header
            CodeGenerationStatics.AddSummaryDocComment(
                writer,
                "Creates a modification object in update mode with the specified conditions, which can be used to do a piecemeal update of the " + tableName + " table." );
            writer.WriteLine(
                "public static " + GetClassName( cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass ) + " CreateForUpdate" + methodNameSuffix + "( " +
                getConditionParameterDeclarations( cn, tableName ) + " ) {" );

            // body

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

            // Set column values that correspond to modification conditions to the values of those conditions. One reason this is important is so the primary
            // key can be retrieved in a consistent way regardless of whether the modification object is an insert or an update.
            writer.WriteLine( "foreach( var condition in mod.conditions ) {" );
            var prefix = "if";
            foreach( var column in columns.AllColumnsExceptRowVersion ) {
                writer.WriteLine( prefix + "( condition is " + DataAccessStatics.GetEqualityConditionClassName( cn, database, tableName, column ) + " )" );
                writer.WriteLine(
                    "mod." + getColumnFieldName( column ) + ".Value = ( condition as " + DataAccessStatics.GetEqualityConditionClassName( cn, database, tableName, column ) +
                    " ).Value;" );
                prefix = "else if";
            }
            writer.WriteLine( "}" );
            writer.WriteLine( writer.NewLine + "mod.markColumnValuesUnchanged();" );

            writer.WriteLine( "return mod;" );
            writer.WriteLine( "}" );
        }
Exemple #10
0
        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
        }
Exemple #11
0
        private static void writeClass(DBConnection cn, string tableName, bool isRevisionHistoryTable, bool isRevisionHistoryClass, int?commandTimeoutSeconds)
        {
            columns = new TableColumns(cn, tableName, isRevisionHistoryClass);

            writer.WriteLine("public partial class " + GetClassName(cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass) + " {");

            var revisionHistorySuffix = GetRevisionHistorySuffix(isRevisionHistoryClass);

            // Write public static methods.
            writeInsertRowMethod(tableName, revisionHistorySuffix, "", columns.KeyColumns);
            writeInsertRowMethod(tableName, revisionHistorySuffix, "WithoutAdditionalLogic", columns.KeyColumns);
            writeUpdateRowsMethod(cn, tableName, revisionHistorySuffix, "");
            writeUpdateRowsMethod(cn, tableName, revisionHistorySuffix, "WithoutAdditionalLogic");
            writeDeleteRowsMethod(cn, tableName, revisionHistorySuffix, true);
            writeDeleteRowsMethod(cn, tableName, revisionHistorySuffix + "WithoutAdditionalLogic", false);
            writePrivateDeleteRowsMethod(cn, tableName, isRevisionHistoryClass, commandTimeoutSeconds);
            writer.WriteLine(
                "static partial void preDelete( List<" + DataAccessStatics.GetTableConditionInterfaceName(cn, database, tableName) + "> conditions, ref " +
                getPostDeleteCallClassName(cn, tableName) + " postDeleteCall );");

            writer.WriteLine("private ModificationType modType;");
            writer.WriteLine("private List<" + DataAccessStatics.GetTableConditionInterfaceName(cn, database, tableName) + "> conditions;");

            foreach (var column in columns.AllColumnsExceptRowVersion)
            {
                writeFieldsAndPropertiesForColumn(column);
            }

            //foreach( var column in columns.DataColumns.Where( i => !columns.KeyColumns.Contains( i ) ) )
            //	FormItemStatics.WriteFormItemGetters( writer, column.GetModificationField() );

            // Write constructors.
            writeCreateForInsertMethod(cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass, revisionHistorySuffix);
            writeCreateForUpdateMethod(cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass, revisionHistorySuffix);
            if (columns.DataColumns.Any())
            {
                writeCreateForSingleRowUpdateMethod(cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass, revisionHistorySuffix);
            }
            writeGetConditionListMethod(cn, tableName);
            writer.WriteLine("private " + GetClassName(cn, tableName, isRevisionHistoryTable, isRevisionHistoryClass) + "() {}");

            if (columns.DataColumns.Any())
            {
                writeSetAllDataMethod();
            }

            // Write execute methods and helpers.
            writeExecuteMethod(tableName);
            writer.WriteLine("partial void preInsert();");
            writer.WriteLine("partial void preUpdate();");
            writeExecuteWithoutAdditionalLogicMethod(tableName);
            writeExecuteInsertOrUpdateMethod(cn, tableName, isRevisionHistoryClass, columns.KeyColumns, columns.IdentityColumn, commandTimeoutSeconds);
            writeAddColumnModificationsMethod(columns.AllNonIdentityColumnsExceptRowVersion);
            if (isRevisionHistoryClass)
            {
                writeCopyLatestRevisionsMethod(cn, tableName, columns.AllNonIdentityColumnsExceptRowVersion, commandTimeoutSeconds);
                DataAccessStatics.WriteGetLatestRevisionsConditionMethod(writer, columns.PrimaryKeyAndRevisionIdColumn.Name);
            }
            writeRethrowAsEwfExceptionIfNecessary();
            writer.WriteLine(
                "static partial void populateConstraintNamesToViolationErrorMessages( Dictionary<string,string> constraintNamesToViolationErrorMessages );");
            writer.WriteLine("partial void postInsert();");
            writer.WriteLine("partial void postUpdate();");
            writeMarkColumnValuesUnchangedMethod();

            writer.WriteLine("}");
        }
Exemple #12
0
 private static string getQueryCacheType(Query query, QueryPostSelectFromClause postSelectFromClause) =>
 DataAccessStatics.GetNamedParamList(info, query.selectFromClause + " " + postSelectFromClause.Value).Any()
                         ? "QueryRetrievalQueryCache<Row>"
                         : "ParameterlessQueryCache<Row>";
Exemple #13
0
 private static string getQueryCacheName(Query query, QueryPostSelectFromClause postSelectFromClause, bool getFieldName) =>
 (getFieldName ? "rows" : "Rows") + postSelectFromClause.name +
 (DataAccessStatics.GetNamedParamList(info, query.selectFromClause + " " + postSelectFromClause.Value).Any() ? "Queries" : "Query");