public a7DbDataComparer(string dbName, string dbA, string dbB, Action <string> log)
        {
            _mergeWithDelete = false;
            _log             = log;
            Srv = new Server(dbName);
            DbA = Srv.Databases[dbA];
            DbB = Srv.Databases[dbB];

            MergeDirection = a7DbComparerDirection.None;
            MergeAtoB      = new a7LambdaCommand(async(o) =>
            {
                if (MergeDirection != a7DbComparerDirection.AtoB)
                {
                    await SetMergeDirection(a7DbComparerDirection.AtoB);
                }
                else
                {
                    await SetMergeDirection(a7DbComparerDirection.None);
                }
            }
                                                 );
            MergeBtoA = new a7LambdaCommand(async(o) =>
            {
                if (MergeDirection != a7DbComparerDirection.BtoA)
                {
                    await SetMergeDirection(a7DbComparerDirection.BtoA);
                }
                else
                {
                    await SetMergeDirection(a7DbComparerDirection.None);
                }
            }
                                            );

            ShowGeneratedQuery = new a7LambdaCommand((o) =>
            {
                var sb = new StringBuilder();
                foreach (var tbl in Tables)
                {
                    if (tbl.Rows != null)
                    {
                        foreach (var rw in tbl.Rows)
                        {
                            if (rw.IsDifferent)
                            {
                                sb.Append(rw.SQL);
                            }
                        }
                    }
                }
                var str = sb.ToString();
                if (string.IsNullOrWhiteSpace(str))
                {
                    MessageBox.Show(
                        "Empty query, please select some at least one difference selector (like A>B or B>A) on a row, table or database level.");
                    return;
                }
                new a7GeneratedQueryWindow(str).Show();
            }
                                                     );

            var tableNamesA    = new List <string>();
            var tableNamesB    = new List <string>();
            var tableNamesAorB = new List <string>();

            Log("Collecting table list");
            foreach (var tbA in DbA.Tables)
            {
                var table = tbA as Table;
                tableNamesA.Add(table.Name);
                if (!tableNamesAorB.Contains(table.Name))
                {
                    tableNamesAorB.Add(table.Name);
                }
            }
            foreach (var tbB in DbB.Tables)
            {
                var table = tbB as Table;
                tableNamesB.Add(table.Name);
                if (!tableNamesAorB.Contains(table.Name))
                {
                    tableNamesAorB.Add(table.Name);
                }
            }

            TableNamesOnlyInA  = new ObservableCollection <string>();
            TableNamesOnlyInB  = new ObservableCollection <string>();
            TableNamesInBothDb = new ObservableCollection <string>();
            Tables             = new ObservableCollection <a7DbTableComparer>();
            Log("Searching tables with differences tables");
            foreach (var tblName in tableNamesAorB)
            {
                if (!tableNamesA.Contains(tblName) && tableNamesB.Contains(tblName))
                {
                    TableNamesOnlyInB.Add(tblName);
                    continue;
                }
                if (!tableNamesB.Contains(tblName) && tableNamesA.Contains(tblName))
                {
                    TableNamesOnlyInA.Add(tblName);
                    continue;
                }
                if (tableNamesA.Contains(tblName) && tableNamesB.Contains(tblName) && tblName != "adminQueriesLog" && tblName != "logExceptions" &&
                    tblName != "logQueries")
                {
                    TableNamesInBothDb.Add(tblName);
                    var tblComp = new a7DbTableComparer(DbA.Tables[tblName], DbB.Tables[tblName], this);
                    if (tblComp.IsDifferentData)
                    {
                        Tables.Add(tblComp);
                    }
                }
            }
        }
        public a7ComparisonRow(DataRow rowA, DataRow rowB, a7DbTableComparer tableComparer, a7DbDataComparer comparer)
        {
            MergeDirection = a7DbComparerDirection.None;
            MergeAtoB      = new a7LambdaCommand((o) =>
            {
                if (MergeDirection != a7DbComparerDirection.AtoB)
                {
                    SetMergeDirection(a7DbComparerDirection.AtoB, false);
                }
                else
                {
                    SetMergeDirection(a7DbComparerDirection.None, false);
                }
            }
                                                 );
            MergeBtoA = new a7LambdaCommand((o) =>
            {
                if (MergeDirection != a7DbComparerDirection.BtoA)
                {
                    SetMergeDirection(a7DbComparerDirection.BtoA, false);
                }
                else
                {
                    SetMergeDirection(a7DbComparerDirection.None, false);
                }
            }
                                            );

            _dataRowA    = rowA;
            _dataRowB    = rowB;
            _comparer    = comparer;
            _tblComparer = tableComparer;
            if (_dataRowA == null && _dataRowB != null)
            {
                IsOnlyInB   = true;
                IsOnlyInA   = false;
                AtoBCaption = "B>X";
                BtoACaption = "B>A";
            }
            else if (_dataRowB == null && _dataRowA != null)
            {
                IsOnlyInB   = false;
                IsOnlyInA   = true;
                AtoBCaption = "A>B";
                BtoACaption = "A>X";
            }
            else
            {
                IsOnlyInA   = false;
                IsOnlyInB   = false;
                AtoBCaption = "A>B";
                BtoACaption = "B>A";
            }
            Fields = new Dictionary <string, a7ComparisonField>();



            IsDifferent = false;

            for (var i = 0; i < tableComparer.ColumnsInBothTables.Count; i++)
            {
                var    colName = tableComparer.ColumnsInBothTables[i];
                object valA    = null;
                if (rowA != null)
                {
                    valA = rowA[colName];
                }
                object valB = null;
                if (rowB != null)
                {
                    valB = rowB[colName];
                }
                Fields.Add(colName, new a7ComparisonField(valA, valB, rowA != null, rowB != null, colName, this._comparer));
                if (valA?.ToString() != valB?.ToString() &&
                    colName != "dbVersion" && colName != "dbTimestamp" && colName != "dbUser")
                {
                    IsDifferent = true;
                }
            }

            for (var i = 0; i < tableComparer.ColumnsOnlyInA.Count; i++)
            {
                var    colName = tableComparer.ColumnsOnlyInA[i];
                object valA    = null;
                if (rowA != null)
                {
                    valA = rowA[colName];
                }
                Fields.Add(colName, new a7ComparisonField(valA, null, true, false, colName, this._comparer));
                IsDifferent = true;
            }

            for (var i = 0; i < tableComparer.ColumnsOnlyInB.Count; i++)
            {
                var    colName = tableComparer.ColumnsOnlyInB[i];
                object valB    = null;
                if (rowB != null)
                {
                    valB = rowB[colName];
                }
                Fields.Add(colName, new a7ComparisonField(null, valB, false, true, colName, this._comparer));
                IsDifferent = true;
            }
        }