public override void Start() { try { Status = TaskStatus.Running; var token = _cancelToken.Token; Task.Run(() => { try { _dtResult = new DataTable(); var tableList = new List<Tuple<string, int, int, int>>().Select(item => new { FullTableName = item.Item1, HasSameColumns = item.Item2, HasPK = item.Item3, MaxRowCountFromBoth = item.Item4 }).ToList(); if (!UserPermissions.Instance.UserSpecificPermissions[Owner.ToUpper()].CopyAndSearchFromDatabaseSeverList.Contains(_databaseServer)) throw new Exception("No permission to use this server."); List<string> tableListRevided = new List<string>(); if (!String.IsNullOrWhiteSpace(_listOfTablesToCompare)) _listOfTablesToCompare.Replace("--", "").Split(',').ToList().ForEach(item => tableListRevided.Add(item.Trim())); AppendOutputText(String.Format("Retrieving list of table to compare...{0}", Environment.NewLine)); var serverToUse = DatabaseServers.Instance.ItemsList.FirstOrDefault(item => item.Name == _databaseServer); try { using (SqlConnection conn = new SqlConnection(serverToUse.ConnectionString + ";Connection Timeout=30")) { SqlMetaData[] meta = new[] { new SqlMetaData("item", SqlDbType.NVarChar, 200), }; var results = tableListRevided.Select(item => { SqlDataRecord newRow = new SqlDataRecord(meta); newRow.SetValues(item); return newRow; }); SqlCommand command = conn.CreateCommand(); command.CommandTimeout = 5 * 60; command.CommandType = CommandType.StoredProcedure; command.CommandText = "dbo.GetTablesForDataCompare"; command.Parameters.Add(new SqlParameter("@FirstDatabaseName", _databaseNameToCompare)); command.Parameters.Add(new SqlParameter("@SecondDatabaseName", _databaseNameToCompareAgaints)); SqlParameter param1 = new SqlParameter("@TablesToCompare", SqlDbType.Structured); param1.TypeName = "dbo.StringList"; param1.Value = tableListRevided.Count > 0 ? results : null; command.Parameters.Add(param1); conn.Open(); SqlDataReader myReader = command.ExecuteReader(CommandBehavior.CloseConnection); while (myReader.Read()) { tableList.Add( new { FullTableName = myReader["FullTableName"].ToString(), HasSameColumns = Int32.Parse(myReader["HasSameColumns"].ToString()), HasPK = Int32.Parse(myReader["HasPK"].ToString()), MaxRowCountFromBoth = Int32.Parse(myReader["MaxRowCountFromBoth"].ToString()) }); } conn.Close(); AppendOutputText(String.Format("Finished retrieving list of table.{0}", Environment.NewLine)); } } catch (Exception ex) { Status = TaskStatus.Failed; this.AppendOutputText(ex.Message); Log.ErrorFormat("Exception while retrieving list of table to compare from server: {0}, exception:{1}", serverToUse.Name, ex.Message); return; } token.ThrowIfCancellationRequested(); int totalCount = tableList.Count; if (totalCount == 0) AppendOutputText(String.Format("There are no tables to compare.{0}", Environment.NewLine)); Parallel.ForEach(tableList, (item, loopState) => { if (token.IsCancellationRequested) { loopState.Stop(); return; } if (item.HasSameColumns == 0) { AppendOutputText(String.Format("Finished {1,4} of {2}. Table {0} will not be compared, column schema difference.{3}", item.FullTableName, Interlocked.Increment(ref _taskProgress), totalCount, Environment.NewLine)); } else if (item.HasPK == 0) { AppendOutputText(String.Format("Finished {1,4} of {2}. Table {0} will not be compared, missing primary key.{3}", item.FullTableName, Interlocked.Increment(ref _taskProgress), totalCount, Environment.NewLine)); } else if (item.MaxRowCountFromBoth == 0) { AppendOutputText(String.Format("Finished {1,4} of {2}. Table {0} will not be compared, empty on both databases.{3}", item.FullTableName, Interlocked.Increment(ref _taskProgress), totalCount, Environment.NewLine)); } else if (_maxTableRowCount.HasValue && item.MaxRowCountFromBoth > _maxTableRowCount.Value) { AppendOutputText(String.Format("Finished {1,4} of {2}. Table {0} will not be compared, rowcount exceding specified limit of {4}.{3}", item.FullTableName, Interlocked.Increment(ref _taskProgress), totalCount, Environment.NewLine, _maxTableRowCount.Value)); } else { try { DataTable dtResults = new DataTable(item.FullTableName); using (SqlConnection conn = new SqlConnection(serverToUse.ConnectionString + ";Connection Timeout=30")) { SqlCommand command = conn.CreateCommand(); command.CommandTimeout = 30 * 60; command.CommandType = CommandType.StoredProcedure; command.CommandText = "dbo.CompareDataInTable"; command.Parameters.Add(new SqlParameter("@TableName", item.FullTableName)); command.Parameters.Add(new SqlParameter("@FirstDatabaseName", _databaseNameToCompare)); command.Parameters.Add(new SqlParameter("@SecondDatabaseName", _databaseNameToCompareAgaints)); SqlDataAdapter dataAdaper = new SqlDataAdapter(command); dataAdaper.Fill(dtResults); AppendOutputText(String.Format("Finished {1,4} of {2}. Finished comparing data for table {0}.{3}", item.FullTableName, Interlocked.Increment(ref _taskProgress), totalCount, Environment.NewLine)); } if (dtResults.Rows.Count > 0) { lock (_sync) { _dtResult.Merge(dtResults); } } } catch (Exception ex) { AppendOutputText(String.Format("Exception during CompareDataInTable for table {0}. Exception:{1}{2}", item.FullTableName, ex.Message, Environment.NewLine)); Log.ErrorFormat("Exception during CompareDataInTable for table {0}. Exception:{1}", item.FullTableName, ex.Message); } } }); token.ThrowIfCancellationRequested(); if (_dtResult.Rows.Count > 0) { _dtResult.DefaultView.Sort = "[TableName] asc, [TableKeyValues] asc"; this.Result = _dtResult.DefaultView.ToTable("Result"); } Status = TaskStatus.Succeeded; } catch(TaskCanceledException) { Status = TaskStatus.Aborted; } catch (Exception ex) { AppendOutputText(ex.Message); Status = TaskStatus.Failed; Log.Error("Failed to compare databases.", ex); } }); }catch(Exception ex) { Log.Error("Unable to start task.", ex); throw; } }
public static List<string> GetTablesForDataTrack(string databaseServer, string databaseName, string tablesToTrackCommaSeparated, string databaseOwner) { try { List<string> sqlStatementList = new List<string>(); DatabaseServerInfo server = DatabaseServers.Instance.ItemsList.First(item => String.Compare(item.Name, databaseServer, true) == 0); List<string> tablesToTrackList = new List<string>(); if (!String.IsNullOrWhiteSpace(tablesToTrackCommaSeparated)) tablesToTrackCommaSeparated.Replace("--", "").Split(',').ToList().ForEach(item => tablesToTrackList.Add(item.Trim())); try { using (SqlConnection conn = new SqlConnection(server.ConnectionString)) { SqlMetaData[] meta = new [] { new SqlMetaData("item", SqlDbType.NVarChar, 200)}; var results = tablesToTrackList.Select(item => { SqlDataRecord newRow = new SqlDataRecord(meta); newRow.SetValues(item); return newRow; }); var command = conn.CreateCommand(); command.CommandType = CommandType.StoredProcedure; command.CommandText = "dbo.GetTablesForDataTrack"; command.Parameters.AddWithValue("@DatabaseName", databaseName); command.Parameters.AddWithValue("@DatabaseOwner", databaseOwner); SqlParameter param1 = new SqlParameter("@TableNames", System.Data.SqlDbType.Structured); param1.TypeName = "dbo.StringList"; param1.Value = tablesToTrackList.Count > 0 ? results : null; command.Parameters.Add(param1); conn.Open(); SqlDataReader myReader = command.ExecuteReader(CommandBehavior.CloseConnection); while (myReader.Read()) { sqlStatementList.Add(myReader.GetString(0)); } } return sqlStatementList; } catch (Exception ex) { Log.Error(String.Format("Problem accessing server: {0}.", server.Name), ex); throw; } } catch (Exception ex) { Log.Error(ex); throw; } }