public DataCompareAssertCompletedEventArgs(DateTime testExecutionTime, string packageName, string taskName, string testName, string assertName, string testResultMsg, bool testPassed, CommandBase assertCommand, DataCompareCommandResults dataCompareCommandResults)
            : base(testExecutionTime, packageName, taskName, testName, assertName, testResultMsg, testPassed, assertCommand)
        {
            if (dataCompareCommandResults == null)
            {
                throw new ArgumentNullException("dataCompareCommandResults");
            }

            DataCompareCommandResults = dataCompareCommandResults;
        }
        public DataCompareAssertCompletedEventArgs(string assertName, TestResult testResult, CommandBase assertCommand, DataCompareCommandResults dataCompareCommandResults)
            : base(assertName, testResult, assertCommand)
        {
            if (dataCompareCommandResults == null)
            {
                throw new ArgumentNullException("dataCompareCommandResults");
            }

            DataCompareCommandResults = dataCompareCommandResults;
        }
        public DataCompareCommandCompletedEventArgs(DateTime completedExecutionTime, string commandName, string parentName, string package, string results, DataCompareCommandResults dataCompareCommandResults, CommandParentType commandParentType)
            : base(completedExecutionTime, commandName, parentName, package, results, commandParentType)
        {
            if (dataCompareCommandResults == null)
            {
                throw new ArgumentNullException("dataCompareCommandResults");
            }

            DataCompareCommandResults = dataCompareCommandResults;
        }
        public override object Execute(Package package, DtsContainer container)
        {
            if (ExpectedDataset == null)
            {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The expectedDataset attribute is {0}, which does not reference a valid dataset.", Properties[PropExpectedDataset].Value));
            }

            if (ExpectedDataset.ConnectionRef == null)
            {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The expected dataset's (\"{0}\") connection does not reference a valid Connection Reference.", Properties[PropExpectedDataset].Value));
            }

            if (string.IsNullOrEmpty(ExpectedDataset.Query))
            {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The expected dataset's (\"{0}\") query is not specified.", Properties[PropExpectedDataset].Value));
            }

            if (ActualDataset == null)
            {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The actualDataset attribute is {0}, which does not reference a valid dataset.", Properties[PropActualDataset].Value));
            }

            if (ActualDataset.ConnectionRef == null)
            {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The actual dataset's (\"{0}\") connection does not reference a valid Connection Reference.", Properties[PropActualDataset].Value));
            }

            if (string.IsNullOrEmpty(ActualDataset.Query))
            {
                throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The actual dataset's (\"{0}\") query is not specified.", Properties[PropActualDataset].Value));
            }

            DbCommand expectedDbCommand = null;
            DbCommand actualDbCommand   = null;

            DataTable expectedDataTable;
            DataTable actualDataTable;

            CommandParentType commandParentType = GetCommandParentType();

            try
            {
                OnCommandStarted(new CommandStartedEventArgs(DateTime.Now, Name, null, null, commandParentType));

                if (!ExpectedDataset.IsResultsStored)
                {
                    expectedDbCommand = Helper.GetCommand(ExpectedDataset.ConnectionRef, ExpectedDataset.Query);
                    expectedDbCommand.Connection.Open();

                    using (IDataReader expectedReader = expectedDbCommand.ExecuteReader())
                    {
                        var ds = new DataSet();

                        ds.Load(expectedReader, LoadOption.OverwriteChanges, new[] { "Results" });

                        if (ds.Tables.Count < 1)
                        {
                            throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The expected dataset (\"{0}\") did not retrieve any data.", Properties[PropExpectedDataset].Value));
                        }

                        expectedDataTable = ds.Tables[0];
                    }
                }
                else
                {
                    if (ExpectedDataset.Results == null || ExpectedDataset.Results.Columns.Count < 1)
                    {
                        throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The expected dataset's (\"{0}\") stored results does not contain data. Populate the Results data table before executing.", Properties[PropExpectedDataset].Value));
                    }

                    expectedDataTable = ExpectedDataset.Results;
                }
            }
            catch (Exception ex)
            {
                OnCommandFailed(new CommandFailedEventArgs(DateTime.Now, Name, null, null, ex.Message, commandParentType));

                throw;
            }
            finally
            {
                if (expectedDbCommand != null)
                {
                    if (expectedDbCommand.Connection != null)
                    {
                        expectedDbCommand.Connection.Close();
                    }

                    expectedDbCommand.Dispose();
                }
            }

            try
            {
                if (!ActualDataset.IsResultsStored)
                {
                    actualDbCommand = Helper.GetCommand(ActualDataset.ConnectionRef, ActualDataset.Query);
                    actualDbCommand.Connection.Open();

                    using (IDataReader actualReader = actualDbCommand.ExecuteReader())
                    {
                        var ds = new DataSet();

                        ds.Load(actualReader, LoadOption.OverwriteChanges, new[] { "Results" });

                        if (ds.Tables.Count < 1)
                        {
                            throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The actual dataset (\"{0}\") did not retrieve any data.", Properties[PropActualDataset].Value));
                        }

                        actualDataTable = ds.Tables[0];
                    }
                }
                else
                {
                    if (ActualDataset.Results == null || ActualDataset.Results.Columns.Count < 1)
                    {
                        throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, "The actual dataset's (\"{0}\") stored results does not contain data. Populate the Results data table before executing.", Properties[PropActualDataset].Value));
                    }

                    actualDataTable = ActualDataset.Results;
                }
            }
            catch (Exception ex)
            {
                OnCommandFailed(new CommandFailedEventArgs(DateTime.Now, Name, null, null, ex.Message, commandParentType));

                throw;
            }
            finally
            {
                if (actualDbCommand != null)
                {
                    if (actualDbCommand.Connection != null)
                    {
                        actualDbCommand.Connection.Close();
                    }

                    actualDbCommand.Dispose();
                }
            }

            bool isComparisonPossible    = true;
            var  expectedDatasetMessages = new List <string>();
            var  actualDatasetMessages   = new List <string>();

            if (expectedDataTable == null || expectedDataTable.Columns.Count < 1)
            {
                isComparisonPossible = false;

                expectedDatasetMessages.Add(string.Format(CultureInfo.CurrentCulture, "The expected dataset (\"{0}\") did not retrieve any data.", Properties[PropExpectedDataset].Value));
            }
            else
            {
                expectedDataTable.AcceptChanges();
            }

            if (actualDataTable == null || actualDataTable.Columns.Count < 1)
            {
                isComparisonPossible = false;

                actualDatasetMessages.Add(string.Format(CultureInfo.CurrentCulture, "The actual dataset (\"{0}\") did not retrieve any data.", Properties[PropActualDataset].Value));
            }
            else
            {
                actualDataTable.AcceptChanges();
            }

            bool isSchemasCompatible;

            if (isComparisonPossible)
            {
                if (expectedDataTable.Columns.Count == actualDataTable.Columns.Count)
                {
                    isSchemasCompatible = true;

                    // Compare each table's columns and ensure that they're the same datatypes at each position.
                    for (int columnIndex = 0; columnIndex < expectedDataTable.Columns.Count; columnIndex++)
                    {
                        if (expectedDataTable.Columns[columnIndex].DataType == actualDataTable.Columns[columnIndex].DataType)
                        {
                            continue;
                        }

                        isSchemasCompatible = false;

                        break;
                    }
                }
                else
                {
                    isSchemasCompatible = false;

                    actualDatasetMessages.Add(string.Format("The expected \"{0}\" and actual \"{1}\" datasets do not have the same columns and/or data types for each column.  Ensure that both datasets return the same number of columns and that each column is the same data type.", Properties[PropExpectedDataset].Value, Properties[PropActualDataset].Value));
                }
            }
            else
            {
                isSchemasCompatible = false;
            }

            var expectedDatasetErrorIndices = new Dictionary <int, IEnumerable <int> >(expectedDataTable != null ? expectedDataTable.Rows.Count : 0);
            var actualDatasetErrorIndices   = new Dictionary <int, IEnumerable <int> >(actualDataTable != null ? actualDataTable.Rows.Count : 0);
            int rowIndex = 0;

            if (expectedDataTable != null && actualDataTable != null)
            {
                for (; rowIndex < expectedDataTable.Rows.Count; rowIndex++)
                {
                    if (rowIndex < actualDataTable.Rows.Count)
                    {
                        DataRow expectedRow = expectedDataTable.Rows[rowIndex];
                        DataRow actualRow   = actualDataTable.Rows[rowIndex];

                        var expectedColumnsDifferent = new List <int>();
                        var actualColumnsDifferent   = new List <int>();

                        for (int columnIndex = 0; columnIndex < expectedRow.ItemArray.Length; columnIndex++)
                        {
                            if (columnIndex < actualRow.ItemArray.Length)
                            {
                                if (!Equals(expectedRow[columnIndex], actualRow[columnIndex]))
                                {
                                    actualColumnsDifferent.Add(columnIndex);
                                }
                            }
                            else
                            {
                                expectedColumnsDifferent.Add(columnIndex);
                            }
                        }

                        // If there are rows that aren't found in the actual dataset or there are additional columns in the the expected dataset.
                        if (expectedColumnsDifferent.Count > 0)
                        {
                            expectedDatasetErrorIndices.Add(rowIndex, expectedColumnsDifferent.Count >= expectedRow.ItemArray.Length ? null : expectedColumnsDifferent);
                        }

                        if (actualColumnsDifferent.Count > 0)
                        {
                            actualDatasetErrorIndices.Add(rowIndex, actualColumnsDifferent.Count >= expectedRow.ItemArray.Length ? null : actualColumnsDifferent);
                        }
                    }
                    else
                    {
                        expectedDatasetErrorIndices.Add(rowIndex, null);
                    }
                }
            }

            if (actualDataTable != null)
            {
                for (; rowIndex < actualDataTable.Rows.Count; rowIndex++)
                {
                    actualDatasetErrorIndices.Add(rowIndex, null);
                }
            }

            bool isResultsSame = actualDatasetErrorIndices.Count < 1 && expectedDatasetErrorIndices.Count < 1;

            var results = new DataCompareCommandResults(ExpectedDataset, ActualDataset, expectedDataTable, actualDataTable, expectedDatasetErrorIndices, actualDatasetErrorIndices, isSchemasCompatible, isResultsSame, expectedDatasetMessages, actualDatasetMessages);

            string resultMessage = isResultsSame ?
                                   string.Format("The datasets \"{0}\" and \"{1}\" are the same.", ExpectedDataset.Name, ActualDataset.Name)
                :
                                   string.Format("{0} row{1} differ{2} between the expected \"{3}\" and actual \"{4}\" datasets.",
                                                 (expectedDatasetErrorIndices.Count + actualDatasetErrorIndices.Count).ToString("N0"),
                                                 actualDatasetErrorIndices.Count == 1 ? string.Empty : "s",
                                                 actualDatasetErrorIndices.Count == 1 ? "s" : string.Empty,
                                                 ExpectedDataset.Name,
                                                 ActualDataset.Name);

            var completedEventArgs = new DataCompareCommandCompletedEventArgs(DateTime.Now, Name, null, null, resultMessage, results, commandParentType);

            if (isResultsSame)
            {
                OnCommandCompleted(completedEventArgs);
            }
            else
            {
                OnCommandFailed(new CommandFailedEventArgs(DateTime.Now, Name, null, null, resultMessage, results, commandParentType));
            }

            return(results);
        }