338 lines · 13.0 KB · C#
RawDownload
//******************************************************************************************************//  DataUpdater.cs - Gbtc////  Copyright © 2018, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  11/12/2018 - Stephen Wills//       Generated original version of source code from code written in 2003.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Data;using System.Data.OleDb;using System.Diagnostics.CodeAnalysis;using System.Text; namespace GSF.Data{    // Note: user must define primary key fields in the database or through code to be used for updates for each table    // in the table collection in order for the updates to occur, hence any tables which have no key fields defined    // yet appear in the table collection will not be updated...     /// <summary>    /// This class defines a common set of functionality that any data operation implementation can use     /// </summary>    public class DataUpdater : BulkDataOperationBase    {        #region [ Members ]         // Events         /// <summary>        /// Disposed event.        /// </summary>        public event EventHandler Disposed;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new <see cref="DataUpdater"/>.        /// </summary>        public DataUpdater()        {        }         /// <summary>        /// Creates a new <see cref="DataUpdater"/>.        /// </summary>        public DataUpdater(string fromConnectString, string toConnectString)            : base(fromConnectString, toConnectString)        {        }         /// <summary>        /// Creates a new <see cref="DataUpdater"/>.        /// </summary>        public DataUpdater(Schema fromSchema, Schema toSchema)            : base(fromSchema, toSchema)        {        }         #endregion         #region [ Methods ]         /// <summary>        /// Close        /// </summary>        public override void Close()        {            base.Close();             if ((object)Disposed != null)                Disposed(this, EventArgs.Empty);        }         /// <summary>        /// Execute this <see cref="DataUpdater"/>        /// </summary>        public override void Execute()        {            List<Table> tablesList = new List<Table>();            Table tableLookup;            int x;             if (m_tableCollection.Count == 0)                Analyze();             if (m_tableCollection.Count == 0)                throw new NullReferenceException("No tables to process even after analyze.");             // We copy the tables into an array list so we can sort and process them in priority order            foreach (Table sourceTable in m_tableCollection)            {                if (sourceTable.Process)                {                    sourceTable.CalculateRowCount();                     if (sourceTable.RowCount > 0)                    {                        tablesList.Add(sourceTable);                        m_overallTotal += sourceTable.RowCount;                    }                }            }             tablesList.Sort((table1, table2) => table1.Priority > table2.Priority ? 1 : (table1.Priority < table2.Priority ? -1 : 0));             // Begin updating data in destination tables            for (x = 0; x <= tablesList.Count - 1; x++)            {                Table table = tablesList[x];                 // Lookup table name in destination datasource                tableLookup = ToSchema.Tables.FindByMapName(table.MapName);                 if ((object)tableLookup != null)                {                    // We can only do Sql updates where key fields are defined...                    if (table.RowCount > 0 && (m_useFromSchemaRI ? table.PrimaryKeyFieldCount : tableLookup.PrimaryKeyFieldCount) > 0)                    {                        // Inform clients of table update                        OnTableProgress(table.Name, true, x + 1, tablesList.Count);                         // Update destination table based on source table records                        ExecuteUpdates(table, tableLookup);                    }                    else                    {                        // Inform clients of table skip                        OnTableProgress(table.Name, false, x + 1, tablesList.Count);                         // If we skipped rows because of lack of key fields, make sure and                        // synchronize overall progress event                        if (table.RowCount > 0)                        {                            m_overallProgress += table.RowCount;                            OnOverallProgress((int)m_overallProgress, (int)m_overallTotal);                        }                    }                }                else                {                    // Inform clients of table skip                    OnTableProgress(table.Name, false, x + 1, tablesList.Count);                }            }             // Perform final update of progress information            OnTableProgress("", false, tablesList.Count, tablesList.Count);        }         /// <summary>        /// Execute a command to update data from source to destination table        /// </summary>        /// <param name="fromTable">Source table</param>        /// <param name="toTable">Destination table</param>        [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]        private void ExecuteUpdates(Table fromTable, Table toTable)        {            Table sourceTable = m_useFromSchemaRI ? fromTable : toTable;            Field lookupField;            Field commonField;             // Progress process variables            int progress = 0;            int totalProgress;             // Bulk update variables            string updateSQLStub;            StringBuilder updateSQL;            StringBuilder whereSQL;            string value;            bool isPrimary;            bool addedFirstUpdate;             // Create a field list of all of the common fields in both tables            // Use toTable as the parent to retrieve the appropriate SQLEncodedValues            Fields fieldsCollection = new Fields(toTable);             foreach (Field fld in fromTable.Fields)            {                // Lookup field name in destination table                lookupField = toTable.Fields[fld.Name];                 if ((object)lookupField != null)                {                    // We currently don't handle binary fields...                    if (!(fld.Type == OleDbType.Binary || fld.Type == OleDbType.LongVarBinary || fld.Type == OleDbType.VarBinary) && !(lookupField.Type == OleDbType.Binary || lookupField.Type == OleDbType.LongVarBinary || lookupField.Type == OleDbType.VarBinary))                    {                        // Copy field information from destination field                        if (m_useFromSchemaRI)                        {                            commonField = new Field(fld.Name, fld.Type);                            commonField.AutoIncrement = fld.AutoIncrement;                        }                        else                        {                            commonField = new Field(lookupField.Name, lookupField.Type);                            commonField.AutoIncrement = lookupField.AutoIncrement;                        }                         fieldsCollection.Add(commonField);                    }                }            }             // Exit if no common field names were found            if (fieldsCollection.Count == 0)            {                m_overallProgress += fromTable.RowCount;                return;            }             totalProgress = fromTable.RowCount;            OnRowProgress(fromTable.Name, 0, totalProgress);            OnOverallProgress((int)m_overallProgress, (int)m_overallTotal);             // Execute source query            using (IDataReader fromReader = fromTable.Connection.ExecuteReader("SELECT " + fieldsCollection.GetList(sqlEscapeFunction: fromTable.Parent.Parent.SQLEscapeName) + " FROM " + fromTable.SQLEscapedName, CommandBehavior.SequentialAccess, Timeout))            {                // Create Sql update stub                updateSQLStub = "UPDATE " + toTable.SQLEscapedName + " SET ";                 // Insert data for each row...                while (fromReader.Read())                {                    updateSQL = new StringBuilder(updateSQLStub);                    whereSQL = new StringBuilder();                    addedFirstUpdate = false;                     // Coerce all field data into proper Sql format                    foreach (Field fld in fieldsCollection)                    {                        try                        {                            fld.Value = fromReader[fld.Name];                        }                        catch (Exception ex)                        {                            fld.Value = "";                            OnSQLFailure("Failed to get field value for [" + sourceTable.Name + "." + fld.Name + "]", ex);                        }                         // Check to see if this is a key field                        lookupField = sourceTable.Fields[fld.Name];                         if ((object)lookupField != null)                            isPrimary = lookupField.IsPrimaryKey;                        else                            isPrimary = false;                         value = fld.SQLEncodedValue;                         if (!value.Equals("NULL", StringComparison.CurrentCultureIgnoreCase))                        {                            if (isPrimary)                            {                                if (whereSQL.Length == 0)                                    whereSQL.Append(" WHERE ");                                else                                    whereSQL.Append(" AND ");                                 whereSQL.Append(fld.SQLEscapedName);                                whereSQL.Append(" = ");                                whereSQL.Append(value);                            }                            else                            {                                if (addedFirstUpdate)                                    updateSQL.Append(", ");                                else                                    addedFirstUpdate = true;                                 updateSQL.Append(fld.SQLEscapedName);                                updateSQL.Append(" = ");                                updateSQL.Append(value);                            }                        }                    }                     if (whereSQL.Length > 0)                    {                        // Add where criteria to Sql update statement                        updateSQL.Append(whereSQL.ToString());                         try                        {                            // Update record in destination table                            if (addedFirstUpdate)                                toTable.Connection.ExecuteNonQuery(updateSQL.ToString(), Timeout);                        }                        catch (Exception ex)                        {                            OnSQLFailure(updateSQL.ToString(), ex);                        }                    }                    else                    {                        OnSQLFailure(updateSQL.ToString(), new DataException("ERROR: No \"WHERE\" criteria was generated for Sql update statement, primary key value missing?  Update not performed"));                    }                     progress += 1;                    m_overallProgress += 1;                     if (progress % RowReportInterval == 0)                    {                        OnRowProgress(fromTable.Name, progress, totalProgress);                        OnOverallProgress((int)m_overallProgress, (int)m_overallTotal);                    }                }                 fromReader.Close();            }             OnRowProgress(fromTable.Name, totalProgress, totalProgress);            OnOverallProgress((int)m_overallProgress, (int)m_overallTotal);        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t