//****************************************************************************************************** // BulkDataOperationBase.cs - Gbtc // // Copyright © 2012, 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 Eclipse Public License -v 1.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/eclipse-1.0.php // // 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: // ---------------------------------------------------------------------------------------------------- // 06/28/2010 - J. Ritchie Carroll // Generated original version of source code. // 08/21/2008 - Mihir Brahmbhatt // Converted to C# extensions. // 09/27/2010 - Mihir Brahmbhatt // Edited code comments. // 12/20/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.ComponentModel; namespace Database { #region [ TableProgressEventHandler ] /// /// Initializes a new instance of the class. /// /// /// /// /// public class TableProgressEventHandler : EventArgs { #region [ Members ] //Variables declaration public string TableName; public bool Executed; public int CurrentTable; public int TotalTables; #endregion #region [ Constructors ] /// /// Default constructor /// public TableProgressEventHandler() : this(default(string), default(bool), default(int), default(int)) { } /// /// Constructor with parameters /// /// Table is currently in progress for migration /// Status of table execution /// Current index of table count /// Total tables need to be processed public TableProgressEventHandler(string tableName, bool executed, int currentTable, int totalTables) { TableName = tableName; Executed = executed; CurrentTable = currentTable; TotalTables = totalTables; } #endregion } #endregion #region [ RowProgressEventHandler ] /// /// Initializes a new instance of the class. /// /// /// /// public class RowProgressEventHandler : EventArgs { #region [ Members ] //Variables Declaration public string TableName; public int CurrentRow; public int TotalRows; #endregion #region [ Constructors ] /// /// Default constructor /// public RowProgressEventHandler() : this(default(string), default(int), default(int)) { } /// /// Constructor with parameters /// /// Table name for which rows are in progress /// Current index of row /// Total rows in table public RowProgressEventHandler(string tableName, int currentRow, int totalRows) { TableName = tableName; CurrentRow = currentRow; TotalRows = totalRows; } #endregion } #endregion #region [ OverallProgressEventHandler ] /// /// Initializes a new instance of the class. /// /// /// public class OverallProgressEventHandler : EventArgs { #region [ Members ] //Variables Declaration public int Current; public int Total; #endregion #region [ Constructors ] /// /// Default constructor /// public OverallProgressEventHandler() : this(default(int), default(int)) { } /// /// Constructor with parameters /// /// Currenct Index of overall progress /// Total Table of overall progress public OverallProgressEventHandler(int current, int total) { Current = current; Total = total; } #endregion } #endregion #region [ OverallProgressEventHandler ] /// /// Initializes a new instance of the class. /// /// /// public class SqlFailureEventHandler : EventArgs { #region [ Members ] //Variables Declaration public string Sql; public Exception Ex; #endregion #region [ Constructors ] /// /// Default constructor /// public SqlFailureEventHandler() : this(default(string), default(Exception)) { } /// /// Constructor with parameters /// /// sql statement that executed /// Exception occured while executing a sql statement public SqlFailureEventHandler(string sql, Exception ex) { Sql = sql; Ex = ex; } #endregion } #endregion #region [ IBulkDataOperation ] /// /// This is the common interface for any bulk data operation /// public interface IBulkDataOperation { /// /// Get the status information of table progress /// event EventHandler> TableProgress; /// /// Get the information of Row progress of table /// event EventHandler> RowProgress; /// /// Get the information of overall progress of Migration utility /// event EventHandler> OverallProgress; /// /// Get the information of exception while processing sql statement /// event EventHandler> SqlFailure; /// /// Get the work table information /// Tables WorkTables { get; } /// /// From schema information /// Schema FromSchema { get; set; } /// /// To Schema information /// Schema ToSchema { get; set; } /// /// Get the row report interval information /// int RowReportInterval { get; set; } /// /// Get or set time out for sql statement /// int Timeout { get; set; } /// /// Execute a method of object /// void Execute(); /// /// Close the object connection /// void Close(); } #endregion /// /// This class defines a common set of functionality that any bulk data operation implementation can use /// public abstract class BulkDataOperationBase : IBulkDataOperation, IDisposable { #region [ Members ] // Fields - Variables Declaration protected ISite ComponentSite; protected Schema schFrom; protected Schema schTo; /// /// Implemetor can use this variable to track overall progress /// protected long intOverallProgress; /// /// This is initialized to the overall total number of records to be processed /// protected long intOverallTotal; /// /// Defines interval for reporting row progress /// private int intRowReportInterval; /// /// Timeout value for Sql operation /// protected int intTimeout; /// /// Tables value /// protected Tables colTables; /// /// Flag to check Referencial Integrity /// protected bool flgUseFromSchemaRI; /// /// List of exclude tables /// private readonly List m_excludedTables = new List(); // Events public event EventHandler> TableProgress; public event EventHandler> RowProgress; //.RowProgress; public event EventHandler> OverallProgress; public event EventHandler> SqlFailure; // Delegates public delegate void TableProgressEventHandler(string TableName, bool Executed, int CurrentTable, int TotalTables); public delegate void RowProgressEventHandler(string TableName, int CurrentRow, int TotalRows); public delegate void OverallProgressEventHandler(int Current, int Total); public delegate void SqlFailureEventHandler(string Sql, Exception ex); #endregion #region [ Constructors ] /// /// Default Constructor /// public BulkDataOperationBase() { intRowReportInterval = 5; intTimeout = 120; flgUseFromSchemaRI = true; } /// /// Constructor with parameters /// /// Source database connection string /// Destination database connection string public BulkDataOperationBase(string FromConnectString, string ToConnectString) : this() { schFrom = new Schema(FromConnectString, TableType.Table, false, false); schTo = new Schema(ToConnectString, TableType.Table, false, false); } /// /// Constructor with parameters /// /// Source Schema /// Destination Schema public BulkDataOperationBase(Schema FromSchema, Schema ToSchema) : this() { schFrom = FromSchema; schTo = ToSchema; } #endregion //protected override void Finalize() //{ // Dispose(true); //} #region [ Properties ] /// /// Get or Set Source schema /// [Browsable(true), Category("Configuration"), Description("Source schema definition.")] public virtual Schema FromSchema { get { return schFrom; } set { schFrom = value; if ((ComponentSite != null)) if (ComponentSite.DesignMode) schFrom.ImmediateClose = false; } } /// /// Get or Set destination schema /// [Browsable(true), Category("Configuration"), Description("Destination schema definition.")] public virtual Schema ToSchema { get { return schTo; } set { schTo = value; if ((ComponentSite != null)) if (ComponentSite.DesignMode) schTo.ImmediateClose = false; } } /// /// Get or Set number of rows to process before raising progress events /// [Browsable(true), Category("Configuration"), Description("Number of rows to process before raising progress events."), DefaultValue(5)] public virtual int RowReportInterval { get { return intRowReportInterval; } set { intRowReportInterval = value; } } /// /// Get or Set Maximum number of seconds to wait when processing a Sql command before timing out. /// [Browsable(true), Category("Configuration"), Description("Maximum number of seconds to wait when processing a Sql command before timing out."), DefaultValue(120)] public virtual int Timeout { get { return intTimeout; } set { intTimeout = value; } } /// /// Get or Set - use referential integrity information from source/to destination database during data processing /// [Browsable(true), Category("Configuration"), Description("Set to True to use referential integrity information from source database during data processing, set to False to use destination database."), DefaultValue(true)] public virtual bool UseFromSchemaReferentialIntegrity { get { return flgUseFromSchemaRI; } set { flgUseFromSchemaRI = value; } } /// /// These are the tables that were found in both source and dest to be used for data operation... /// [Browsable(false)] public virtual Tables WorkTables { get { return colTables; } } /// /// Get list of tables to be excluded during data processing /// public List ExcludedTables { get { return m_excludedTables; } } #endregion #region [ Methods ] /// /// Dispose /// /// protected virtual void Dispose(bool disposing) { Close(); } /// /// Close source and destinaction schema /// public virtual void Close() { if ((schFrom != null)) schFrom.Close(); if ((schTo != null)) schTo.Close(); schFrom = null; schTo = null; GC.SuppressFinalize(this); } /// /// Dispose /// void IDisposable.Dispose() { Close(); } /// /// Analyze data schema before data processing /// public virtual void Analyze() { //Table tbl;// = default(Table); Table tblLookup;// = default(Table); schFrom.ImmediateClose = false; schFrom.Analyze(); schTo.ImmediateClose = false; schTo.Analyze(); m_excludedTables.Sort(); colTables = new Tables(schFrom); // We preprocess which tables we are going to access for data operation... foreach (Table tbl in schFrom.Tables) { // Bypass excluded tables if (m_excludedTables.BinarySearch(tbl.MapName) < 0) { // Lookup table name in destination datasource by map name tblLookup = schTo.Tables.FindByMapName(tbl.MapName); if ((tblLookup != null)) { intOverallTotal += tbl.RowCount; // If user requested to use referential integrity of destination tables then // we use process priority of those tables instead... if (!flgUseFromSchemaRI) tbl.Priority = tblLookup.Priority; tbl.Process = true; colTables.Add(tbl); } } } } public abstract void Execute(); //Derived classes can't directly raise base class events, hence the following... /// /// Raise an event if table change in data processing /// /// Table name in data processing /// Status of data processing on table /// current table index in data processing /// total table count in data processing protected virtual void RaiseEvent_TableProgress(string TableName, bool Executed, int CurrentTable, int TotalTables) { if (TableProgress != null) { TableProgress(this, new TableProgressEventHandler(TableName, Executed, CurrentTable, TotalTables)); //TableProgress(this, new TableProgressEventHandler(this,)); //(eventhandler(new EventArgs{TableName, Executed, CurrentTable, TotalTables}); } } /// /// Raise an event while chage row in data processing /// /// Table name in data processing /// current row index in data processing /// total rows needs to be process in data processing protected virtual void RaiseEvent_RowProgress(string TableName, int CurrentRow, int TotalRows) { if (RowProgress != null) { RowProgress(this, new RowProgressEventHandler(TableName, CurrentRow, TotalRows)); //RowProgress(TableName, CurrentRow, TotalRows); } } /// /// Raise an event to show overall progress of data processing /// /// Current index of tables in data processing /// Total table count in data processing protected virtual void RaiseEvent_OverallProgress(int Current, int Total) { if (OverallProgress != null) { OverallProgress(this, new OverallProgressEventHandler(Current, Total)); //OverallProgress(Current, Total); } } /// /// Raise an event if sql statement fail /// /// sql statement information /// exception information protected virtual void RaiseEvent_SqlFailure(string Sql, Exception ex) { if (SqlFailure != null) { SqlFailure(this, new SqlFailureEventHandler(Sql, ex)); //SqlFailure(Sql, ex); } } #endregion } }