Esempio n. 1
0
        /// <summary>
        /// Builds a script that will create a new table from the specified <see cref="LogTableDefinition" />.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" />.</param>
        /// <returns>A <see cref="SqlCommand" /> for a CREATE TABLE script based on the specified <see cref="LogTableDefinition" />.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="table" /> is null.</exception>
        public static SqlCommand BuildCreateTable(LogTableDefinition table)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            StringBuilder script = new StringBuilder();

            script.AppendLine($"CREATE TABLE [dbo].[{table.Name}](");

            // Build column definitions
            foreach (LogTableColumn column in table)
            {
                string nullConstraint = column.AllowNulls ? "NULL" : "NOT NULL";
                script.AppendLine($"[{column.Name}] {column.DataType} {nullConstraint},");
            }

            // Add primary key constraint
            script.AppendLine($"CONSTRAINT [PK_{table.Name}] PRIMARY KEY CLUSTERED([{table.PrimaryKey}] ASC)");
            script.AppendLine($"WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON[PRIMARY]");

            // Close script and return
            script.AppendLine(") ON[PRIMARY]");
            return(new SqlCommand(script.ToString()));
        }
Esempio n. 2
0
        /// <summary>
        /// Builds a script that will insert data from the specified <see cref="LogTableRecord" />.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" /> for the database table.</param>
        /// <param name="record">The <see cref="LogTableRecord" /> containing the data to insert.</param>
        /// <returns>A <see cref="SqlCommand" /> for an INSERT script that inserts the data from the specified <see cref="LogTableRecord" />.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="table" /> is null.
        /// <para>or</para>
        /// <paramref name="record" /> is null.
        /// </exception>
        public static SqlCommand BuildInsert(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            SqlParameterHelper helper = new SqlParameterHelper(table, record);

            StringBuilder script = new StringBuilder();

            script.Append($"INSERT INTO [dbo].[{table.Name}](");
            script.Append(string.Join(", ", helper.GetColumnNames()));
            script.Append(") VALUES (");
            script.Append(string.Join(", ", helper.GetColumnParams()));
            script.Append(")");

            // Add parameters for all values
            SqlCommand command = new SqlCommand(script.ToString());

            command.Parameters.AddRange(helper.GetSqlParameters().ToArray());
            return(command);
        }
Esempio n. 3
0
        /// <summary>
        /// Builds a script that will update data from the specified <see cref="LogTableRecord" />.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" /> for the database table.</param>
        /// <param name="record">The <see cref="LogTableRecord" /> containing the data to update.</param>
        /// <returns>A <see cref="SqlCommand" /> for an UPDATE script that updates the data from the specified <see cref="LogTableRecord" />.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="table" /> is null.
        /// <para>or</para>
        /// <paramref name="record" /> is null.
        /// </exception>
        public static SqlCommand BuildUpdate(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            SqlParameterHelper helper = new SqlParameterHelper(table, record);

            StringBuilder script = new StringBuilder();

            script.Append($"UPDATE [dbo].[{table.Name}] SET ");
            script.Append(string.Join(", ", helper.GetUpdateAssignments()));
            script.Append(" WHERE ");
            script.Append(helper.GetPrimaryKeyWhereClause());

            // Add parameters for all values
            SqlCommand command = new SqlCommand(script.ToString());

            command.Parameters.AddRange(helper.GetSqlParameters().ToArray());
            return(command);
        }
Esempio n. 4
0
        /// <summary>
        /// Updates data from the specified <see cref="LogTableRecord" /> into the table designated by the <see cref="LogTableDefinition" />.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" />.</param>
        /// <param name="record">The <see cref="LogTableRecord" />.</param>
        /// <returns><c>true</c> if submission was successful, <c>false</c> otherwise.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="table" /> is null.
        /// <para>or</para>
        /// <paramref name="record" /> is null.
        /// </exception>
        public bool Update(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            LogTrace($"UPDATE request received for {table.Name} (primary key = {record[table.PrimaryKey]})");
            DataLogDatabaseResult result = _writer.Update(table, record);
            bool updateSuccessful        = result.Success;

            // If the operation failed, try the alternate (if one exists)
            if (!updateSuccessful && _alternateWriter != null)
            {
                LogTrace($"UPDATE failed.  Attempting update to alternate database.");
                DataLogDatabaseResult alternateResult = _alternateWriter.Update(table, record);
                updateSuccessful = alternateResult.Success;
            }

            // If the operation hasn't succeeded, check to see if we should add this to the cache.
            if (!updateSuccessful)
            {
                _cache?.Add(table, record, false);
            }

            return(updateSuccessful);
        }
Esempio n. 5
0
        private static bool CreateTable(SqlConnection connection, LogTableDefinition table)
        {
            try
            {
                using (SqlCommand create = DataLogSqlBuilder.BuildCreateTable(table))
                {
                    LogTrace($"SQL command: {create.CommandText}");
                    create.Connection = connection;
                    create.ExecuteNonQuery();
                }

                if (table.Any(n => n.Name == _sessionIdColumn))
                {
                    using (SqlCommand key = DataLogSqlBuilder.BuildForeignKey(_sessionSummaryTable, _sessionIdColumn, table.Name, _sessionIdColumn))
                    {
                        LogTrace($"Building foreign key: {key.CommandText}");
                        key.Connection = connection;
                        key.ExecuteNonQuery();
                    }
                }

                return(true);
            }
            catch (SqlException ex)
            {
                LogError($"Table {table.Name} could not be created: {ex.Message}");
                return(false);
            }
        }
Esempio n. 6
0
 public DataLogCacheData(LogTableDefinition table, LogTableRecord record, bool isInsert)
 {
     Table    = table;
     Record   = record;
     IsInsert = isInsert;
     Retries  = 0;
 }
Esempio n. 7
0
        public DataLogDatabaseResult Insert(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            LogTrace($"INSERT {table.Name} (primary key = {record[table.PrimaryKey]})");

            DataLogDatabaseResult result;

            using (SqlCommand insert = DataLogSqlBuilder.BuildInsert(table, record))
            {
                result = new DataLogDatabaseResult(table.Name, insert);
                try
                {
                    using (SqlConnection connection = new SqlConnection(_connectionString.ToString()))
                    {
                        connection.Open();
                        insert.Connection = connection;

                        try
                        {
                            insert.ExecuteNonQuery();
                        }
                        catch (SqlException ex) when(ex.Message.Contains("Invalid object"))
                        {
                            // Table doesn't exist - create it and try again
                            LogDebug($"Generating new table {table.Name}");
                            if (CreateTable(connection, table))
                            {
                                LogDebug($"Table {table.Name} created.");
                                LogTrace($"Retrying INSERT {table.Name}");
                                insert.ExecuteNonQuery();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    result.Error = ex.Message;
                }
            }

            if (!result.Success)
            {
                LogWarn($"INSERT {table.Name} failed: {result.Error}");
                LogTrace($"SQL command: " + result.Command);
                LogTrace($"SQL parameters: {string.Join("; ", result.Parameters.Select(n => $"{n.Key}={n.Value}"))}");
            }

            return(result);
        }
Esempio n. 8
0
            public SqlParameterHelper(LogTableDefinition table, LogTableRecord record)
            {
                _primaryKey = table.PrimaryKey;
                _record     = record;

                // Ignore any columns that have no associated value in the LogTableRecord
                foreach (LogTableColumn column in table.Columns)
                {
                    if (_record.ContainsKey(column.Name))
                    {
                        _columns.Add(column);
                    }
                }
            }
        /// <summary>
        /// Updates data from the specified <see cref="LogTableRecord" /> into the table designated by the <see cref="LogTableDefinition" />.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" />.</param>
        /// <param name="record">The <see cref="LogTableRecord" />.</param>
        /// <returns><c>true</c> if submission was successful, <c>false</c> otherwise.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="table" /> is null.
        /// <para>or</para>
        /// <paramref name="record" /> is null.
        /// </exception>
        public bool Update(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            return(Channel.Update(table, record));
        }
Esempio n. 10
0
        public DataLogDatabaseResult Update(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            LogTrace($"UPDATE {table.Name} (primary key = {record[table.PrimaryKey]})");

            DataLogDatabaseResult result;

            using (SqlCommand update = DataLogSqlBuilder.BuildUpdate(table, record))
            {
                result = new DataLogDatabaseResult(table.Name, update);
                try
                {
                    using (SqlConnection connection = new SqlConnection(_connectionString.ToString()))
                    {
                        connection.Open();
                        update.Connection = connection;

                        int affectedRows = update.ExecuteNonQuery();
                        if (affectedRows == 0)
                        {
                            result.Error = "No rows were affected.";
                        }
                    }
                }
                catch (Exception ex)
                {
                    result.Error = ex.Message;
                }
            }

            if (!result.Success)
            {
                LogWarn($"UPDATE {table.Name} failed: {result.Error}");
                LogTrace($"SQL command: " + result.Command);
                LogTrace($"SQL parameters: {string.Join("; ", result.Parameters.Select(n => $"{n.Key}={n.Value}"))}");
            }

            return(result);
        }
Esempio n. 11
0
        // update 3.3.1 notes:
        // Add CruiseID fields to Log and Stem tables
        // Change is fully backwards compatible with prior versions
        private void UpdateTo_3_3_1(CruiseDatastore db)
        {
            var curVersion    = db.DatabaseVersion;
            var targetVersion = "3.3.1";

            var fKeys = db.ExecuteScalar <string>("PRAGMA foreign_keys;");

            db.Execute("PRAGMA foreign_keys=OFF;");

            db.BeginTransaction();
            try
            {
                // need to drop any views associated with tables we are rebuilding
                db.Execute("DROP VIEW LogGradeError;");

                var logTableDef  = new LogTableDefinition();
                var stemTableDef = new StemTableDefinition();

                db.Execute("DROP TABLE Log_Tombstone;");
                db.Execute("DROP TABLE Stem_Tombstone;");

                db.Execute(logTableDef.CreateTombstoneTable);
                db.Execute(stemTableDef.CreateTombstoneTable);

                RebuildTable(db, logTableDef, customFieldMaps: new KeyValuePair <string, string>[]
                {
                    new KeyValuePair <string, string>("CruiseID", "(SELECT CruiseID FROM Tree WHERE Tree.TreeID = Log.TreeID)"),
                });

                RebuildTable(db, stemTableDef, customFieldMaps: new KeyValuePair <string, string>[]
                {
                    new KeyValuePair <string, string>("CruiseID", "(SELECT CruiseID FROM Tree WHERE Tree.TreeID = Stem.TreeID)"),
                });

                var lgeViewDef = new LogGradeErrorViewDefinition();
                db.Execute(lgeViewDef.CreateView);

                SetDatabaseVersion(db, targetVersion);
                db.CommitTransaction();

                db.Execute($"PRAGMA foreign_keys={fKeys};");
            }
            catch (Exception e)
            {
                db.RollbackTransaction();
                throw new SchemaUpdateException(curVersion, targetVersion, e);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Inserts data from the specified <see cref="LogTableRecord" /> into the table designated by the <see cref="LogTableDefinition" />.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" />.</param>
        /// <param name="record">The <see cref="LogTableRecord" />.</param>
        /// <returns><c>true</c> if submission was successful, <c>false</c> otherwise.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="table" /> is null.
        /// <para>or</para>
        /// <paramref name="record" /> is null.
        /// </exception>
        public bool Insert(LogTableDefinition table, LogTableRecord record)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            LogTrace($"INSERT request received for {table.Name} (primary key = {record[table.PrimaryKey]})");
            DataLogDatabaseResult result = _writer.Insert(table, record);
            bool insertSuccessful        = result.Success;

            // If the operation failed, try the alternate (if one exists)
            if (!insertSuccessful && _alternateWriter != null)
            {
                LogTrace($"INSERT failed.  Attempting insert to alternate database.");
                DataLogDatabaseResult alternateResult = _alternateWriter.Insert(table, record);
                insertSuccessful = alternateResult.Success;
            }

            // If the operation hasn't succeeded, check to see if we should add this to the cache.
            if (!insertSuccessful && _cache != null)
            {
                if (result.Error.Contains("Violation of PRIMARY KEY constraint", StringComparison.OrdinalIgnoreCase))
                {
                    // Bypass the cache for primary key violations
                    result.Retries = -1;
                    CacheOperationsRetried?.Invoke(this, new DataLogCacheEventArgs(new[] { result }));
                }
                else
                {
                    _cache.Add(table, record, true);
                }
            }

            return(insertSuccessful);
        }
Esempio n. 13
0
        /// <summary>
        /// Adds the specified log table data to the cache.
        /// </summary>
        /// <param name="table">The <see cref="LogTableDefinition" />.</param>
        /// <param name="record">The <see cref="LogTableRecord" />.</param>
        /// <param name="isInsert">if set to <c>true</c> this data should be processed as an insert.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="table" /> is null.
        /// <para>or</para>
        /// <paramref name="record" /> is null.
        /// </exception>
        public void Add(LogTableDefinition table, LogTableRecord record, bool isInsert)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (record == null)
            {
                throw new ArgumentNullException(nameof(record));
            }

            string   operation = isInsert ? "INSERT" : "UPDATE";
            string   fileName  = $"{table.Name} {operation} {record[table.PrimaryKey]}.xml";
            FileInfo file      = new FileInfo(Path.Combine(_cacheLocation.FullName, fileName));

            LogTrace($"Adding cache file {file.Name}");
            DataLogCacheData cacheData = new DataLogCacheData(table, record, isInsert);

            WriteCacheData(file, cacheData);
        }