aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Synchronization/Local/LocalDBComparer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/Tango.Synchronization/Local/LocalDBComparer.cs')
-rw-r--r--Software/Visual_Studio/Tango.Synchronization/Local/LocalDBComparer.cs200
1 files changed, 200 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.Synchronization/Local/LocalDBComparer.cs b/Software/Visual_Studio/Tango.Synchronization/Local/LocalDBComparer.cs
new file mode 100644
index 000000000..63f2ecfaa
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Synchronization/Local/LocalDBComparer.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Logging;
+
+namespace Tango.Synchronization.Local
+{
+ /// <summary>
+ /// Represents an <see cref="ILocalDataBase"/> synchronization engine.
+ /// </summary>
+ /// <seealso cref="System.IDisposable" />
+ public class LocalDBComparer : IDisposable
+ {
+ /// <summary>
+ /// Gets the master SQL.
+ /// </summary>
+ public ILocalDataBase MasterSQL { get; private set; }
+
+ /// <summary>
+ /// Gets the slave SQL.
+ /// </summary>
+ public ILocalDataBase SlaveSQL { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LocalDBComparer"/> class.
+ /// </summary>
+ /// <param name="masterSQL">The master SQL.</param>
+ /// <param name="slaveSQL">The slave SQL.</param>
+ public LocalDBComparer(ILocalDataBase masterSQL, ILocalDataBase slaveSQL)
+ {
+ MasterSQL = masterSQL;
+ SlaveSQL = slaveSQL;
+ }
+
+ /// <summary>
+ /// Compares the master and slave SQL data base and returns a collection of <see cref="Diff"/>.
+ /// </summary>
+ /// <returns></returns>
+ public List<Diff> Compare()
+ {
+ LogManager.Log("Comparing databases " + Path.GetFileName(MasterSQL.Source) + " <=> " + Path.GetFileName(SlaveSQL.Source));
+
+ LogManager.Log("Loading master tables...");
+ MasterSQL.LoadTables();
+
+ LogManager.Log("Loading slave tables...");
+ SlaveSQL.LoadTables();
+
+ List<Diff> diffs = new List<Diff>();
+
+ foreach (var masterTable in MasterSQL.Tables)
+ {
+ LogManager.Log("Comparing table " + masterTable.TableName);
+ LogManager.Log("Searching table " + masterTable.TableName + " on slave...");
+
+ var slaveTable = SlaveSQL.Tables.SingleOrDefault(x => x.TableName == masterTable.TableName); //Get matching slave table on slave db.
+
+ if (slaveTable == null) //Table not found on slave.
+ {
+ LogManager.Log("Table not found on slave, adding difference.");
+ //Clone table from slave db to master db including records!
+ diffs.Add(new Diff(DiffAction.AddTableToSlave, String.Format("Add table {0} to slave", masterTable.TableName), () => SlaveSQL.CloneTableFrom(MasterSQL, masterTable), SlaveSQL.GetCloneTableFromCommand(MasterSQL, masterTable)));
+ continue;
+ }
+
+ LogManager.Log("Table found, comparing columns...");
+
+ foreach (DataColumn masterColumn in masterTable.Columns)
+ {
+ LogManager.Log("Searching for column " + masterColumn.ColumnName + " on slave...");
+
+ var slaveColumn = slaveTable.Columns[masterColumn.ColumnName]; //Get matching slave column on slave table.
+
+ if (slaveColumn == null) //Slave column not found.
+ {
+ LogManager.Log("Column not found on slave, adding difference.");
+ //Add column to slave table.
+ diffs.Add(new Diff(DiffAction.AddColumnToSlave, String.Format("Add column {0} to slave table", masterColumn.ColumnName), () => SlaveSQL.AddColumn(masterTable, masterColumn), SlaveSQL.GetAddColumnCommand(masterTable, masterColumn)));
+ }
+
+ LogManager.Log("Column found.");
+ }
+
+ List<DataRow> addToSlave = new List<DataRow>();
+ List<DataRow> updateSlave = new List<DataRow>();
+ List<DataRow> addToMaster = new List<DataRow>();
+ List<DataRow> updateMaster = new List<DataRow>();
+
+ LogManager.Log("Comparing rows...");
+
+ int count = 0;
+
+ foreach (DataRow masterRow in masterTable.Rows)
+ {
+ LogManager.Log("Comparing row " + count++);
+
+ String guid = masterRow.Field<String>(Constants.GUID);
+
+ LogManager.Log("Searching for row with GUID " + guid + " on slave table...");
+
+ //Get Matching slave row.
+ DataRow slaveRow = slaveTable.AsEnumerable().SingleOrDefault(x => x.Field<String>(Constants.GUID) == guid);
+
+ if (slaveRow != null)
+ {
+ LogManager.Log("Slave row found, comparing dates...");
+
+ DateTime masterDate = masterRow.Field<DateTime>(Constants.LAST_UPDATED);
+ DateTime slaveDate = slaveRow.Field<DateTime>(Constants.LAST_UPDATED);
+
+ if (masterDate > slaveDate)
+ {
+ LogManager.Log("Master => Slave Update " + masterDate.ToSQLiteDateString() + ", adding difference.");
+ updateSlave.Add(masterRow);
+ }
+ else if (slaveDate > masterDate)
+ {
+ LogManager.Log("Master <= Slave Update " + masterDate.ToSQLiteDateString() + ", adding difference.");
+ updateMaster.Add(slaveRow);
+ }
+ else
+ {
+ LogManager.Log("Master <=> Slave No Update.");
+ }
+ }
+ else
+ {
+ LogManager.Log("Slave row not found, adding difference.");
+ addToSlave.Add(masterRow);
+ }
+ }
+
+ LogManager.Log("Done comparing rows...");
+
+ LogManager.Log("Searching for missing rows on master...");
+
+ foreach (DataRow slaveRow in slaveTable.Rows)
+ {
+ String guid = slaveRow.Field<String>(Constants.GUID);
+
+ LogManager.Log("Searching for row with GUID " + guid + " on master table...");
+
+ //Get Matching slave row.
+ DataRow masterRow = masterTable.AsEnumerable().SingleOrDefault(x => x.Field<String>(Constants.GUID) == guid);
+
+ if (masterRow == null)
+ {
+ LogManager.Log("Master row not found, adding difference.");
+ addToMaster.Add(slaveRow);
+ }
+ else
+ {
+ LogManager.Log("Master row found.");
+ }
+ }
+
+ LogManager.Log("Done searching for missing rows on master...");
+
+ foreach (var row in addToSlave)
+ {
+ diffs.Add(new Diff(DiffAction.AddRowToSlave, String.Format("Add row to slave table {0}", slaveTable.TableName), () => SlaveSQL.AddRow(slaveTable, row), SlaveSQL.GetAddRowCommand(slaveTable, row)));
+ }
+
+ foreach (var row in addToMaster)
+ {
+ diffs.Add(new Diff(DiffAction.AddRowToMaster, String.Format("Add row to master table {0}", masterTable.TableName), () => MasterSQL.AddRow(masterTable, row), MasterSQL.GetAddRowCommand(masterTable, row)));
+ }
+
+ foreach (var row in updateSlave)
+ {
+ diffs.Add(new Diff(DiffAction.UpdateRowInSlave, String.Format("Update row in slave table {0}", slaveTable.TableName), () => SlaveSQL.UpdateRow(slaveTable, row), SlaveSQL.GetUpdateRowCommand(slaveTable, row)));
+ }
+
+ foreach (var row in updateMaster)
+ {
+ diffs.Add(new Diff(DiffAction.UpdateRowInMaster, String.Format("Update row in master table {0}", masterTable.TableName), () => MasterSQL.UpdateRow(masterTable, row), MasterSQL.GetUpdateRowCommand(masterTable, row)));
+ }
+
+ LogManager.Log("Done comparing table " + masterTable.TableName);
+ }
+
+ LogManager.Log("Databases comparison completed.");
+
+ return diffs;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ MasterSQL.Dispose();
+ SlaveSQL.Dispose();
+ }
+ }
+}