private void RaiseSqlRowsCopiedEvent(long lRowsCopied, clsThreadCopy oTc) { SqlRowsCopiedDelegate temp = SqlRowsCopied; if (temp != null) { temp(this, lRowsCopied, oTc); } }
private void RaiseThreadFinishedEvent(clsThreadCopy oTc, String sErr) { SqlThreadFinishedDelegate temp = ThreadFinished; if (temp != null) { temp(this, oTc, sErr); } }
/// <summary> /// Function called by each thread created in Copy function. /// It calls the clsThreadCopy´s CopyData function /// when the copy process of each thread has come to end through the ThreadLocker object. /// By calling to the RaiseThreadFinishedEvent function it fires a public event which can be captured. /// </summary> /// <param name="o">clsThreadCopy object</param> private void CopyData(object o) { clsThreadCopy oTc = (clsThreadCopy)o; String sRet = ""; sRet = oTc.CopyData(); RaiseThreadFinishedEvent(oTc, sRet); lock (oThreadLocker) { iNumThreads--; Monitor.Pulse(oThreadLocker); } }
/// <summary> /// Starts the process to copy data. /// </summary> /// <param name="bAppendData">If false, the destination table will be truncated.</param> /// <returns>Empty string if everything was ok. Else returns the error's message.</returns> public String Copy(bool bAppendData) { //We are going to need one destination connection and as many source connections as number of parallel threads. DbConnection sqlDest; DbConnection[] sqlSource; if (tDestinationBBDDType == BBDDType.SqlServer) { sqlDest = new SqlConnection(sDestinationConnectionString); } else { sqlDest = new OracleConnection(sDestinationConnectionString); } if (tSourceBBDDType == BBDDType.SqlServer) { sqlSource = new SqlConnection[iNumThreads]; } else { sqlSource = new OracleConnection[iNumThreads]; } byte byConnectionsOpened = 0; String sRet = ""; try { //We open the connections for (int m = 0; m < iNumThreads; m++) { if (tSourceBBDDType == BBDDType.SqlServer) { sqlSource[m] = (DbConnection) new SqlConnection(sSourceConnectionString); } else { sqlSource[m] = (DbConnection) new OracleConnection(sSourceConnectionString); } sqlSource[m].Open(); byConnectionsOpened++; } sqlDest.Open(); //We check the filter select. if (!string.IsNullOrEmpty(sSelectFilter)) { sRet = FillSelectFilterValues(ref sqlSource[0]); if (sRet != "") { throw new Exception(sRet); } } String[][] sRangeLowKeys = new String[iNumThreads][]; String[][] sRangeHighKeys = new String[iNumThreads][]; int[] iSize = new int[iNumThreads]; String sIndexName = ""; String sIndexField = ""; //We check if destination table exists. sRet = CheckDestinationTable(bAppendData, sqlDest); if (sRet != "") { throw new Exception(sRet); } //if heap method we skip the index statistics. if ((!bHeapMethod)) { //We check if the source table is clustered indexed. sRet = CheckSourceTable(sqlSource[0], ref sIndexName, ref sIndexField, ref bHeapMethod); if (sRet != "") { throw new Exception(sRet); } //Looking at source table clustered index´s statistics, we calculate nearly equal row //based ranges to balance the parallel copy of data. if (!bHeapMethod) { sRet = CalculateRangeKeys(sIndexName, sIndexField, sqlSource[0], ref sRangeLowKeys, ref sRangeHighKeys, ref iSize); if (sRet != "") { throw new Exception(sRet); } } } //We check which SqlBulkCopy options that has been selected. int iBcOptions = 0; if (bTabLock) { iBcOptions += (int)SqlBulkCopyOptions.TableLock; } if (bKeepIdentity) { iBcOptions += (int)SqlBulkCopyOptions.KeepIdentity; } if (bKeepNulls) { iBcOptions += (int)SqlBulkCopyOptions.KeepNulls; } if (bCheckConstraints) { iBcOptions += (int)SqlBulkCopyOptions.CheckConstraints; } if (bFireTriggers) { iBcOptions += (int)SqlBulkCopyOptions.FireTriggers; } oTc = new clsThreadCopy[iNumThreads]; for (int i = 0; i < iNumThreads; i++) { //We initialize and configure with different source connection,ranges,size..etc //as many clsThreadCopy´s instances as number of threads will execute in parallel. oTc[i] = new clsThreadCopy(); oTc[i].IdThread = i; oTc[i].SqlSource = sqlSource[i]; oTc[i].SRangeLowKeys = sRangeLowKeys[i]; oTc[i].SRangeHighKeys = sRangeHighKeys[i]; oTc[i].SValuesFilter = sValuesFilter; oTc[i].Size = iSize[i]; oTc[i].SDest = sDestinationConnectionString; oTc[i].SSourceTable = sSourceTable; oTc[i].SSourceTableScheme = sSourceTableScheme; oTc[i].SDestTable = sDestTable; oTc[i].SIndexField = sIndexField; oTc[i].IBcOptions = iBcOptions; oTc[i].INotifyAfter = iNotifyAfter; oTc[i].IIndexFieldDataType = iIndexFieldDataType; oTc[i].NoLock = bNoLock; oTc[i].HeapMethod = bHeapMethod; oTc[i].NumThreads = iNumThreads; oTc[i].SourcebbddType = SourceBBDDType; oTc[i].DestbbddType = DestinationBBDDType; //Each time the clsThreadCopy fires the SqlRowsCopiedThreadEvent event it will call to the OnSqlRowsCopied function. oTc[i].SqlRowsCopiedThreadEvent += new clsThreadCopy.SqlRowsCopiedEventDelegate(OnSqlRowsCopied); WaitCallback w = new WaitCallback(CopyData); //For each instance of clsThreadCopy we create one thread which call CopyData function. ThreadPool.QueueUserWorkItem(w, oTc[i]); } //We wait until all threads end. lock (oThreadLocker) { while (iNumThreads > 0) { Monitor.Wait(oThreadLocker); } } } catch (Exception e) { return(e.Message.ToString()); } finally { //We close connections. for (int i = 0; i < byConnectionsOpened; i++) { if (sqlSource[i].State == System.Data.ConnectionState.Open) { sqlSource[i].Close(); } } if (sqlDest.State == System.Data.ConnectionState.Open) { sqlDest.Close(); } } return(""); }