diff --git a/.gitignore b/.gitignore
index aa8441b67..815d68d8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,8 @@ GenCode128/bin
GenCode128/obj
GraphLib/bin
GraphLib/obj
+MergeResultsDBs/bin
+MergeResultsDBs/obj
TracingDB/bin
TracingDB/obj
ResetBatchNr/bin
diff --git a/MergeResultsDBs/App.config b/MergeResultsDBs/App.config
new file mode 100644
index 000000000..56efbc7b5
--- /dev/null
+++ b/MergeResultsDBs/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MergeResultsDBs/MergeResultsDBs.csproj b/MergeResultsDBs/MergeResultsDBs.csproj
new file mode 100644
index 000000000..277607a7f
--- /dev/null
+++ b/MergeResultsDBs/MergeResultsDBs.csproj
@@ -0,0 +1,84 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}
+ Exe
+ Properties
+ MergeResultsDBs
+ MergeResultsDBs
+ v4.7.2
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\FluentNHibernate.2.0.3.0\lib\net40\FluentNHibernate.dll
+
+
+ ..\packages\Iesi.Collections.4.0.0.4000\lib\net40\Iesi.Collections.dll
+
+
+ ..\packages\log4net.2.0.2\lib\net40-full\log4net.dll
+
+
+ ..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll
+
+
+ ..\packages\NHibernate.4.0.4.4000\lib\net40\NHibernate.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {743df7db-c7b6-42eb-986d-0f485e5588e4}
+ Config
+
+
+ {9d0dcc88-dc81-47eb-9fdd-4c3907871bfb}
+ Results
+
+
+
+
+
\ No newline at end of file
diff --git a/MergeResultsDBs/Program.cs b/MergeResultsDBs/Program.cs
new file mode 100644
index 000000000..04d6e621e
--- /dev/null
+++ b/MergeResultsDBs/Program.cs
@@ -0,0 +1,190 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using log4net;
+using NHibernate;
+using FluentNHibernate;
+using Results;
+using Results.Entities;
+
+namespace MergeResultsDBs
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("A range of records from the 2nd database will be appended to the 1st database.");
+ Console.WriteLine("Enter the 1st (target) database name:");
+ string firstDB = Console.ReadLine();
+ Console.WriteLine("Enter the 2nd database name:");
+ string secondDB = Console.ReadLine();
+ Console.WriteLine("Enter range of batch numbers from the 2nd DB to append to the 1st DB (start-end):");
+ string range = Console.ReadLine();
+
+ ISession session1;
+ IList componentsList;
+ int componentsListInitialCount;
+ IList testDataList;
+ int testDataListInitialCount;
+ IList waterMeterDataList;
+ int waterMeterDataListInitialCount;
+ try
+ {
+ DB.ConnectionString = string.Format("SERVER=localhost; DATABASE={0}; UID=root; PASSWORD=kraken; CHARSET=utf8;", firstDB);
+ session1 = DB.CreateSession();
+
+ componentsList = session1.QueryOver().List();
+ componentsListInitialCount = componentsList.Count;
+
+ testDataList = session1.QueryOver().List();
+ testDataListInitialCount = testDataList.Count();
+
+ waterMeterDataList = session1.QueryOver().List();
+ waterMeterDataListInitialCount = waterMeterDataList.Count();
+ }
+ catch (Exception exc)
+ {
+ MessageBox.Show(string.Format("Cannot open the 1st database:\r\n{0}", exc.Message));
+ return;
+ }
+
+ ISession session2;
+ IList oriComponentsList;
+ IList oriTestDataList;
+ IList oriWMDataList;
+ try
+ {
+ DB.ConnectionString = string.Format("SERVER=localhost; DATABASE={0}; UID=root; PASSWORD=kraken; CHARSET=utf8;", secondDB);
+ session2 = DB.CreateSession();
+
+ oriComponentsList = session2.QueryOver().List();
+ oriTestDataList = session2.QueryOver().List();
+ oriWMDataList = session2.QueryOver().List();
+ }
+ catch (Exception exc)
+ {
+ MessageBox.Show(string.Format("Cannot open the 2nd database:\r\n{0}", exc.Message));
+ return;
+ }
+
+ int batchNrStart;
+ int batchNrEnd;
+ string[] fields = range.Split(new char[] { '-' });
+ if (fields.Length != 2 ||
+ !int.TryParse(fields[0], out batchNrStart) ||
+ !int.TryParse(fields[1], out batchNrEnd) ||
+ batchNrEnd < batchNrStart)
+ {
+ MessageBox.Show("Invalid range of batch numbers");
+ return;
+ }
+
+ Console.WriteLine(string.Format("Appending batches {0}-{1} from DB {2} to DB {3}", batchNrStart, batchNrEnd, secondDB, firstDB));
+ Console.WriteLine("Press 'y' or 'Y' to start, anything else to abort");
+ string response = Console.ReadLine();
+ if (response != "y" && response != "Y")
+ {
+ return;
+ }
+
+ Console.WriteLine("PROCESSING DATABASES ...");
+
+ for (int batchNr = batchNrStart; batchNr <= batchNrEnd; batchNr++)
+ {
+ Console.Write(string.Format("{0} ", batchNr));
+
+ /// Copy one batch from the 2nd to the 1st database
+ var oriBatches = session2.QueryOver()
+ .Where(x => (x.BatchNr == batchNr))
+ .List();
+ if (oriBatches.Count != 1) continue;
+
+ ///---------------------------------------------------------------
+ Batch oriBatch = oriBatches[0];
+
+ var transaction = session1.BeginTransaction();
+ try
+ {
+ Batch batch = new Batch(oriBatch);
+
+ oriBatch.TestRslts = session2.QueryOver()
+ .Where(x => (x.Batch.Id == oriBatch.Id))
+ .List();
+ foreach (var oriTR in oriBatch.TestRslts)
+ {
+ /// Find appropriate Components
+ Components components = oriTR.Components == null
+ ? null
+ : Components.UpdateList(componentsList, new Components(oriTR.Components));
+ if (components != null) session1.SaveOrUpdate(components);
+
+ /// Find appropriate TestData
+ TestData testData = TestData.UpdateList(testDataList, new TestData(oriTR.TestData));
+ session1.SaveOrUpdate(testData);
+
+ TestRslt tr = new TestRslt();
+ tr.CopyContentFrom(oriTR);
+ tr.Batch = batch;
+ tr.Components = components;
+ tr.TestData = testData;
+
+ batch.TestRslts.Add(tr);
+ session1.SaveOrUpdate(tr);
+ }
+
+ oriBatch.WaterMeters = session2.QueryOver()
+ .Where(x => (x.Batch.Id == oriBatch.Id))
+ .List();
+ foreach (var oriWM in oriBatch.WaterMeters)
+ {
+ /// Find appropriate WaterMeterData
+ WaterMeterData wmData = WaterMeterData.UpdateList(waterMeterDataList, new WaterMeterData(oriWM.WaterMeterData));
+ session1.SaveOrUpdate(wmData);
+
+ WaterMeter wm = new WaterMeter();
+ wm.CopyContentFrom(oriWM);
+ wm.Batch = batch;
+ wm.WaterMeterData = wmData;
+
+ foreach (var oriMTR in oriWM.MeterTestRslts)
+ {
+ MeterTestRslt mtr = new MeterTestRslt(oriMTR);
+ mtr.WaterMeter = wm;
+ mtr.TestRslt = batch.TestRslts.FirstOrDefault(x => (x.Name() == oriMTR.TestRslt.Name() &&
+ x.Part == oriMTR.TestRslt.Part &&
+ x.RepetitionNr == oriMTR.TestRslt.RepetitionNr));
+ if (mtr.TestRslt == null)
+ {
+ throw new Exception("Something strange happened");
+ }
+
+ wm.MeterTestRslts.Add(mtr);
+ session1.SaveOrUpdate(mtr);
+ }
+
+ batch.WaterMeters.Add(wm);
+ session1.SaveOrUpdate(wm);
+ }
+
+ session1.SaveOrUpdate(batch);
+ transaction.Commit();
+ }
+ catch
+ {
+ transaction.Rollback();
+ throw new Exception("Commit failed - transaction reverted");
+ }
+ }
+ Console.WriteLine();
+
+ session1.Flush();
+ session1.Close();
+ session2.Close();
+ Console.WriteLine("Successfully completed");
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/MergeResultsDBs/Properties/AssemblyInfo.cs b/MergeResultsDBs/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..bde0f44ed
--- /dev/null
+++ b/MergeResultsDBs/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MergeResultsDBs")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MergeResultsDBs")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f7543f83-5414-4010-ac3f-3af4b6864812")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TBF.sln b/TBF.sln
index 4c5262117..6ef689be3 100644
--- a/TBF.sln
+++ b/TBF.sln
@@ -79,6 +79,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamInterfaceTest", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamMeter", "DataStreamMeter\DataStreamMeter.csproj", "{E6925701-57A6-4167-B5C4-BF670F1DE310}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MergeResultsDBs", "MergeResultsDBs\MergeResultsDBs.csproj", "{9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -343,6 +345,16 @@ Global
{E6925701-57A6-4167-B5C4-BF670F1DE310}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E6925701-57A6-4167-B5C4-BF670F1DE310}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E6925701-57A6-4167-B5C4-BF670F1DE310}.Release|x86.ActiveCfg = Release|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {9786D0A8-BA9A-41F6-9E61-C7B2B76D4C08}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/clean.bat b/clean.bat
index cafdc074f..0e1943158 100644
--- a/clean.bat
+++ b/clean.bat
@@ -26,6 +26,8 @@ rmdir /s /q GenCode128\bin
rmdir /s /q GenCode128\obj
rmdir /s /q GraphLib\bin
rmdir /s /q GraphLib\obj
+rmdir /s /q MergeResultsDBs\bin
+rmdir /s /q MergeResultsDBs\obj
rmdir /s /q TracingDB\bin
rmdir /s /q TracingDB\obj
rmdir /s /q ResetBatchNr\bin