diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs b/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs
index 0c2250c1b1..58f53e587a 100644
--- a/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs
+++ b/Application/ResearchDataManagementPlatform/WindowManagement/ActivateItems.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
@@ -163,9 +164,9 @@ public ActivateItems(ITheme theme, RefreshBus refreshBus, DockPanel mainDockPane
IsAbleToLaunchSubprocesses = true;
}
- protected override ICoreChildProvider GetChildProvider()
+ protected override ICoreChildProvider GetChildProvider(bool force = false)
{
- var provider = base.GetChildProvider();
+ var provider = base.GetChildProvider(force);
if (RefreshBus != null) RefreshBus.ChildProvider = provider;
@@ -534,13 +535,13 @@ public PersistableObjectCollectionDockContent Activate(IObjectCollectionControl
return floatable;
}
- public void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e)
+ public void RefreshBus_DoWork(object sender, DoWorkEventArgs e)
{
// if we don't want to do selective refresh or can't (because partial refreshes are not supported on the type)
- if (HardRefresh || !UserSettings.SelectiveRefresh || !CoreChildProvider.SelectiveRefresh(e.Object))
+ if (HardRefresh || !UserSettings.SelectiveRefresh || !CoreChildProvider.SelectiveRefresh((IMapsDirectlyToDatabaseTable)e.Argument))
{
//update the child provider with a full refresh
- GetChildProvider();
+ GetChildProvider(true);
HardRefresh = false;
}
@@ -550,7 +551,7 @@ public void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e)
private void RefreshProblemProviders()
{
foreach (var p in ProblemProviders)
- p.RefreshProblems(CoreChildProvider);
+ p.RefreshProblems(RefreshBus.ChildProvider);
}
///
diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableObjectCollectionDockContent.cs b/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableObjectCollectionDockContent.cs
index b61a2f7db7..af8c230442 100644
--- a/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableObjectCollectionDockContent.cs
+++ b/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableObjectCollectionDockContent.cs
@@ -68,7 +68,7 @@ protected override string GetPersistString()
}
- public override void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e)
+ public override void RefreshBus_DoWork(object sender, DoWorkEventArgs e)
{
var newTabName = _control.GetTabName();
@@ -78,7 +78,7 @@ public override void RefreshBus_RefreshObject(object sender, RefreshObjectEventA
TabText = newTabName;
//pass the info on to the control
- _control.RefreshBus_RefreshObject(sender, e);
+ _control.RefreshBus_DoWork(sender, e);
}
public override void HandleUserRequestingTabRefresh(IActivateItems activator)
diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableSingleDatabaseObjectDockContent.cs b/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableSingleDatabaseObjectDockContent.cs
index 42a5c9777e..9fde7e24f6 100644
--- a/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableSingleDatabaseObjectDockContent.cs
+++ b/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/PersistableSingleDatabaseObjectDockContent.cs
@@ -4,8 +4,6 @@
// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with RDMP. If not, see .
-using System.ComponentModel;
-using System.Windows.Forms;
using Rdmp.Core.CommandExecution;
using Rdmp.Core.Curation.Data;
using Rdmp.Core.Curation.Data.Dashboarding;
@@ -16,6 +14,9 @@
using Rdmp.UI.Refreshing;
using Rdmp.UI.TestsAndSetup.ServicePropogation;
using ResearchDataManagementPlatform.WindowManagement.ExtenderFunctionality;
+using System.ComponentModel;
+using System.Windows.Forms;
+using static Rdmp.UI.Refreshing.IRefreshBusSubscriber;
namespace ResearchDataManagementPlatform.WindowManagement.ContentWindowTracking.Persistence;
@@ -61,14 +62,22 @@ protected override string GetPersistString()
DatabaseObject.GetType().FullName + s + DatabaseObject.ID;
}
- public override void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e)
+ public override void RefreshBus_DoWork(object sender, DoWorkEventArgs e)
{
- var newTabName = ((IRDMPSingleDatabaseObjectControl)Control).GetTabName();
-
- if (ParentForm is CustomFloatWindow floatWindow)
- floatWindow.Text = newTabName;
-
- TabText = newTabName;
+ if (this.InvokeRequired)
+ {
+ RefreshCallback rb = new RefreshCallback(RefreshBus_DoWork);
+ this.Invoke(rb, sender, e);
+ }
+ else
+ {
+ var newTabName = ((IRDMPSingleDatabaseObjectControl)Control).GetTabName();
+
+ if (ParentForm is CustomFloatWindow floatWindow)
+ floatWindow.Text = newTabName;
+
+ TabText = newTabName;
+ }
}
public override void HandleUserRequestingTabRefresh(IActivateItems activator)
diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/RDMPSingleControlTab.cs b/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/RDMPSingleControlTab.cs
index ec1e1b8e69..a637361e63 100644
--- a/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/RDMPSingleControlTab.cs
+++ b/Application/ResearchDataManagementPlatform/WindowManagement/ContentWindowTracking/Persistence/RDMPSingleControlTab.cs
@@ -51,7 +51,7 @@ public RDMPSingleControlTab(RefreshBus refreshBus, Control c)
Control = c;
}
- public virtual void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e)
+ public virtual void RefreshBus_DoWork(object sender, DoWorkEventArgs e)
{
}
diff --git a/Application/ResearchDataManagementPlatform/WindowManagement/HomePane/HomeUI.cs b/Application/ResearchDataManagementPlatform/WindowManagement/HomePane/HomeUI.cs
index 4f57024a56..6a6c7d2e54 100644
--- a/Application/ResearchDataManagementPlatform/WindowManagement/HomePane/HomeUI.cs
+++ b/Application/ResearchDataManagementPlatform/WindowManagement/HomePane/HomeUI.cs
@@ -4,7 +4,6 @@
// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with RDMP. If not, see .
-using System;
using Rdmp.Core;
using Rdmp.Core.CommandExecution.AtomicCommands;
using Rdmp.Core.CommandExecution.AtomicCommands.CatalogueCreationCommands;
@@ -18,6 +17,9 @@
using Rdmp.UI.ItemActivation;
using Rdmp.UI.Refreshing;
using Rdmp.UI.TestsAndSetup.ServicePropogation;
+using System;
+using System.ComponentModel;
+using static Rdmp.UI.Refreshing.IRefreshBusSubscriber;
namespace ResearchDataManagementPlatform.WindowManagement.HomePane;
@@ -79,8 +81,16 @@ protected override void OnLoad(EventArgs e)
_activator.RefreshBus.EstablishLifetimeSubscription(this);
}
- public void RefreshBus_RefreshObject(object sender, RefreshObjectEventArgs e)
+ public void RefreshBus_DoWork(object sender, DoWorkEventArgs e)
{
- BuildCommandLists();
+ if (boxCatalogue.InvokeRequired)
+ {
+ RefreshCallback rb = new RefreshCallback(RefreshBus_DoWork);
+ this.Invoke(rb, sender, e);
+ }
+ else
+ {
+ BuildCommandLists();
+ }
}
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f43dcd3d3d..a7242d3fff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [9.1.1] - Unreleased
+## [9.1.1] - 2025-12-02
- Allow Atlassian service workers to write to Confluence from RDMP
## [9.1.0] - 2025-11-24
diff --git a/Documentation/CodeTutorials/CreatingANewCollectionTreeNode.md b/Documentation/CodeTutorials/CreatingANewCollectionTreeNode.md
index e57f599f8c..8fa65ee9fc 100644
--- a/Documentation/CodeTutorials/CreatingANewCollectionTreeNode.md
+++ b/Documentation/CodeTutorials/CreatingANewCollectionTreeNode.md
@@ -138,7 +138,7 @@ private void AddChildren(ExtractionConfigurationsNode extractionConfigurationsNo
children.Add(config);
}
- AddToDictionaries(children, descendancy);
+ //AddToDictionaries(children, descendancy);
}
```
@@ -247,7 +247,7 @@ private void AddChildren(ExtractionConfigurationsNode extractionConfigurationsNo
children.Add(config);
}
- AddToDictionaries(children, descendancy);
+ //AddToDictionaries(children, descendancy);
}
private void AddChildren(FrozenExtractionConfigurationsNode frozenExtractionConfigurationsNode, DescendancyList descendancy)
@@ -262,7 +262,7 @@ private void AddChildren(FrozenExtractionConfigurationsNode frozenExtractionConf
children.Add(config);
}
- AddToDictionaries(children, descendancy);
+ //AddToDictionaries(children, descendancy);
}
```
Now when you run RDMP, the final tree should look something like:
diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRefreshBrokenCohortsTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRefreshBrokenCohortsTests.cs
index b2420034c2..0cce242bc4 100644
--- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRefreshBrokenCohortsTests.cs
+++ b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandRefreshBrokenCohortsTests.cs
@@ -11,16 +11,18 @@
using Rdmp.Core.Providers;
using Rdmp.Core.Repositories;
using Rdmp.Core.ReusableLibraryCode.Checks;
+using Rdmp.Core.Startup;
namespace Rdmp.Core.Tests.CommandExecution;
internal class ExecuteCommandRefreshBrokenCohortsTests
{
[Test]
- public void TestBrokenCohort()
+ public void TestBrokenCohort()//todo
{
+ Startup.Startup.PreStartup();
var repo = new MemoryDataExportRepository();
-
+
var ect = new ExternalCohortTable(repo, "yarg", FAnsi.DatabaseType.MicrosoftSQLServer)
{
Server = "IDontExist",
@@ -29,7 +31,6 @@ public void TestBrokenCohort()
ReleaseIdentifierField = "haha"
};
ect.SaveToDatabase();
-
var cohort = new ExtractableCohort
{
Repository = repo,
@@ -44,7 +45,9 @@ public void TestBrokenCohort()
{
DisallowInput = true
};
-
+ activator.Publish(ect);
+ activator.Publish(cohort);
+ _ = ((DataExportChildProvider)activator.CoreChildProvider).ProjectNumberToCohortsDictionary;
Assert.That(((DataExportChildProvider)activator.CoreChildProvider).ForbidListedSources, Has.Count.EqualTo(1));
var cmd = new ExecuteCommandRefreshBrokenCohorts(activator)
diff --git a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandSimilarTests.cs b/Rdmp.Core.Tests/CommandExecution/ExecuteCommandSimilarTests.cs
deleted file mode 100644
index ac0b8e05a5..0000000000
--- a/Rdmp.Core.Tests/CommandExecution/ExecuteCommandSimilarTests.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) The University of Dundee 2018-2019
-// This file is part of the Research Data Management Platform (RDMP).
-// RDMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License along with RDMP. If not, see .
-
-using NUnit.Framework;
-using Rdmp.Core.CommandExecution;
-using Rdmp.Core.CommandExecution.AtomicCommands;
-using Rdmp.Core.Curation.Data;
-using System.Linq;
-
-namespace Rdmp.Core.Tests.CommandExecution;
-
-public class ExecuteCommandSimilarTests : CommandCliTests
-{
- [Test]
- public void FindSameName_MixedCaps()
- {
- var cata1 = new Catalogue(Repository, "Bob");
- var cata2 = new Catalogue(Repository, "bob");
-
- var activator = new ThrowImmediatelyActivator(RepositoryLocator);
- var cmd = new ExecuteCommandSimilar(activator, cata1, false);
-
- Assert.That(cmd.Matched.Single(), Is.EqualTo(cata2));
-
- cata1.DeleteInDatabase();
- cata2.DeleteInDatabase();
- }
-
- [Test]
- public void FindDifferent_ColumnInfosSame()
- {
- var c1 = WhenIHaveA();
- var c2 = WhenIHaveA();
-
- var activator = new ThrowImmediatelyActivator(RepositoryLocator);
- var cmd = new ExecuteCommandSimilar(activator, c1, true);
-
- Assert.That(cmd.Matched, Is.Empty);
-
- c1.DeleteInDatabase();
- c2.DeleteInDatabase();
- }
-
- [Test]
- public void FindDifferent_ColumnInfosDiffer_OnType()
- {
- var c1 = WhenIHaveA();
- c1.Data_type = "varchar(10)";
-
- var c2 = WhenIHaveA();
- c2.Data_type = "varchar(20)";
-
- var activator = new ThrowImmediatelyActivator(RepositoryLocator);
- var cmd = new ExecuteCommandSimilar(activator, c1, true);
-
- Assert.That(cmd.Matched.Single(), Is.EqualTo(c2));
-
- c1.DeleteInDatabase();
- c2.DeleteInDatabase();
- }
-
- [Test]
- public void FindDifferent_ColumnInfosDiffer_OnCollation()
- {
- var c1 = WhenIHaveA();
- c1.Collation = "troll doll";
-
- var c2 = WhenIHaveA();
- c2.Collation = "durdur";
-
- var activator = new ThrowImmediatelyActivator(RepositoryLocator);
- var cmd = new ExecuteCommandSimilar(activator, c1, true);
-
- Assert.That(cmd.Matched.Single(), Is.EqualTo(c2));
-
- c1.DeleteInDatabase();
- c2.DeleteInDatabase();
- }
-}
\ No newline at end of file
diff --git a/Rdmp.Core.Tests/CommandExecution/TestCommandsAreSupported.cs b/Rdmp.Core.Tests/CommandExecution/TestCommandsAreSupported.cs
index 5f9a5cd1c8..d89a039120 100644
--- a/Rdmp.Core.Tests/CommandExecution/TestCommandsAreSupported.cs
+++ b/Rdmp.Core.Tests/CommandExecution/TestCommandsAreSupported.cs
@@ -156,7 +156,6 @@ public void Init()
[TestCase(typeof(ExecuteCommandSetUserSetting))]
[TestCase(typeof(ExecuteCommandShow))]
[TestCase(typeof(ExecuteCommandShowRelatedObject))]
- [TestCase(typeof(ExecuteCommandSimilar))]
[TestCase(typeof(ExecuteCommandSyncTableInfo))]
[TestCase(typeof(ExecuteCommandUnfreezeExtractionConfiguration))]
[TestCase(typeof(ExecuteCommandUnMergeCohortIdentificationConfiguration))]
diff --git a/Rdmp.Core.Tests/Curation/Anonymisation/ANOTableTests.cs b/Rdmp.Core.Tests/Curation/Anonymisation/ANOTableTests.cs
index c981a6165c..671220246d 100644
--- a/Rdmp.Core.Tests/Curation/Anonymisation/ANOTableTests.cs
+++ b/Rdmp.Core.Tests/Curation/Anonymisation/ANOTableTests.cs
@@ -215,7 +215,7 @@ public void SubstituteANOIdentifiers_2CHINumbers()
}
[Test]
- public void SubstituteANOIdentifiers_PreviewWithoutPush()
+ public void SubstituteANOIdentifiers_PreviewWithoutPush()//todo
{
var anoTable = GetANOTable();
anoTable.NumberOfCharactersToUseInAnonymousRepresentation = 0;
diff --git a/Rdmp.Core.Tests/Curation/Integration/AllKeywordsDescribedTest.cs b/Rdmp.Core.Tests/Curation/Integration/AllKeywordsDescribedTest.cs
index 82afafa465..b935f152a4 100644
--- a/Rdmp.Core.Tests/Curation/Integration/AllKeywordsDescribedTest.cs
+++ b/Rdmp.Core.Tests/Curation/Integration/AllKeywordsDescribedTest.cs
@@ -77,7 +77,7 @@ public void AllForeignKeysDescribed()
}
[Test]
- public void AllUserIndexesDescribed()
+ public void AllUserIndexesDescribed()//todo
{
var allIndexes = new List();
diff --git a/Rdmp.Core.Tests/DataExport/DataRelease/S3BucketReleaseDestinationTests.cs b/Rdmp.Core.Tests/DataExport/DataRelease/S3BucketReleaseDestinationTests.cs
index 18c44ae9e2..6f877b9ba1 100644
--- a/Rdmp.Core.Tests/DataExport/DataRelease/S3BucketReleaseDestinationTests.cs
+++ b/Rdmp.Core.Tests/DataExport/DataRelease/S3BucketReleaseDestinationTests.cs
@@ -82,7 +82,7 @@ private static void SetArgs(IArgument[] args, Dictionary values)
}
[Test]
- public void AWSLoginTest()
+ public void AWSLoginTest()//todo
{
var awss3 = new AWSS3("minio", Amazon.RegionEndpoint.EUWest2);
Assert.DoesNotThrow(() => MakeBucket("logintest"));
@@ -90,7 +90,7 @@ public void AWSLoginTest()
}
[Test]
- public void ReleaseToAWSBasicTest()
+ public void ReleaseToAWSBasicTest()//todo
{
MakeBucket("releasetoawsbasictest");
DoExtraction();
@@ -293,7 +293,7 @@ public void BadBucket()
[Test]
- public void LocationAlreadyExists()
+ public void LocationAlreadyExists()//todo
{
MakeBucket("locationalreadyexist");
diff --git a/Rdmp.Core.Tests/DataExport/ProjectCohortIdentificationConfigurationAssociationTests.cs b/Rdmp.Core.Tests/DataExport/ProjectCohortIdentificationConfigurationAssociationTests.cs
index ac70883cbb..adcf1e5e3f 100644
--- a/Rdmp.Core.Tests/DataExport/ProjectCohortIdentificationConfigurationAssociationTests.cs
+++ b/Rdmp.Core.Tests/DataExport/ProjectCohortIdentificationConfigurationAssociationTests.cs
@@ -59,9 +59,8 @@ public void TestOrphanCic()
});
//error should be reported in top right of program
- var ex = Assert.Throws(() =>
- new DataExportChildProvider(new RepositoryProvider(memory), null, ThrowImmediatelyCheckNotifier.Quiet,
- null));
+ var dx = new DataExportChildProvider(new RepositoryProvider(memory), null, ThrowImmediatelyCheckNotifier.Quiet,null);
+ var ex = Assert.Throws(() => _ = dx.ProjectRootFolder);
Assert.That(
ex.Message, Does.Match(@"Failed to find Associated Cohort Identification Configuration with ID \d+ which was supposed to be associated with my proj"));
@@ -70,6 +69,7 @@ public void TestOrphanCic()
IgnoreAllErrorsCheckNotifier.Instance, null);
//the orphan cic should not appear in the tree view under Project=>Cohorts=>Associated Cics
+ var x = childProvider.GetChildren(p);
var cohorts = childProvider.GetChildren(p).OfType().Single();
var cics = childProvider.GetChildren(cohorts).OfType()
.First();
diff --git a/Rdmp.Core/Caching/Pipeline/CachingPipelineUseCase.cs b/Rdmp.Core/Caching/Pipeline/CachingPipelineUseCase.cs
index dd92878929..a33dce611c 100644
--- a/Rdmp.Core/Caching/Pipeline/CachingPipelineUseCase.cs
+++ b/Rdmp.Core/Caching/Pipeline/CachingPipelineUseCase.cs
@@ -114,7 +114,7 @@ public ICacheFileSystemDestination CreateDestinationOnly(IDataLoadEventListener
///
/// Design time types
///
- private CachingPipelineUseCase() : base(new Type[]
+ public CachingPipelineUseCase() : base(new Type[]
{
typeof(ICacheFetchRequestProvider),
typeof(IPermissionWindow),
diff --git a/Rdmp.Core/CohortCommitting/Pipeline/CohortCreationRequest.cs b/Rdmp.Core/CohortCommitting/Pipeline/CohortCreationRequest.cs
index d28b8974ff..e2c301433e 100644
--- a/Rdmp.Core/CohortCommitting/Pipeline/CohortCreationRequest.cs
+++ b/Rdmp.Core/CohortCommitting/Pipeline/CohortCreationRequest.cs
@@ -241,7 +241,7 @@ public int ImportAsExtractableCohort(bool deprecateOldCohortOnSuccess, bool migr
///
/// Design time types
///
- private CohortCreationRequest() : base(new Type[]
+ public CohortCreationRequest() : base(new Type[]
{
typeof(FlatFileToLoad),
typeof(CohortIdentificationConfiguration),
diff --git a/Rdmp.Core/CohortCommitting/Pipeline/CreateTableFromAggregateUseCase.cs b/Rdmp.Core/CohortCommitting/Pipeline/CreateTableFromAggregateUseCase.cs
index dd596cf24f..142300b26d 100644
--- a/Rdmp.Core/CohortCommitting/Pipeline/CreateTableFromAggregateUseCase.cs
+++ b/Rdmp.Core/CohortCommitting/Pipeline/CreateTableFromAggregateUseCase.cs
@@ -72,7 +72,7 @@ protected override IDataFlowPipelineContext GenerateContextImpl()
///
/// Design time types
///
- private CreateTableFromAggregateUseCase()
+ public CreateTableFromAggregateUseCase()
: base(new[]
{
typeof(AggregateConfiguration),
diff --git a/Rdmp.Core/CohortCreation/Execution/CohortIdentificationTaskExecution.cs b/Rdmp.Core/CohortCreation/Execution/CohortIdentificationTaskExecution.cs
index 6b61a4143b..739cec065b 100644
--- a/Rdmp.Core/CohortCreation/Execution/CohortIdentificationTaskExecution.cs
+++ b/Rdmp.Core/CohortCreation/Execution/CohortIdentificationTaskExecution.cs
@@ -69,7 +69,7 @@ internal void GetCohortAsync(int commandTimeout)
using var cmdCount = _target.GetCommand(CountSQL, con);
cmdCount.CommandTimeout = commandTimeout;
- var identifiersReader = cmdCount.ExecuteReaderAsync(_cancellationTokenSource.Token);
+ using var identifiersReader = cmdCount.ExecuteReaderAsync(_cancellationTokenSource.Token);
identifiersReader.Wait(_cancellationTokenSource.Token);
using var rIds = identifiersReader.Result;
@@ -85,7 +85,7 @@ internal void GetCohortAsync(int commandTimeout)
using var cmdCountCumulative = _target.GetCommand(_cumulativeSQL, con);
cmdCountCumulative.CommandTimeout = commandTimeout;
- var cumulativeIdentifiersRead = cmdCountCumulative.ExecuteReaderAsync(_cancellationTokenSource.Token);
+ using var cumulativeIdentifiersRead = cmdCountCumulative.ExecuteReaderAsync(_cancellationTokenSource.Token);
cumulativeIdentifiersRead.Wait(_cancellationTokenSource.Token);
using var rCumulative = cumulativeIdentifiersRead.Result;
CumulativeIdentifiers.Load(rCumulative);
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddNewGovernanceDocument.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddNewGovernanceDocument.cs
index 8e2306845c..12b6dc71c1 100644
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddNewGovernanceDocument.cs
+++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAddNewGovernanceDocument.cs
@@ -52,7 +52,7 @@ public override void Execute()
return;
var doc = new GovernanceDocument(BasicActivator.RepositoryLocator.CatalogueRepository, p, f);
- Publish(_period);
+ Publish(doc);
Emphasise(doc);
Activate(doc);
}
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAssociateCatalogueWithLoadMetadata.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAssociateCatalogueWithLoadMetadata.cs
index 8b35a984c2..3b4d9c20ca 100644
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAssociateCatalogueWithLoadMetadata.cs
+++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandAssociateCatalogueWithLoadMetadata.cs
@@ -100,10 +100,9 @@ public override void Execute()
}
cata.SaveToDatabase();
//associate them
- _loadMetadata.LinkToCatalogue(cata);
+ var linkage = _loadMetadata.LinkToCatalogue(cata);
+ Publish(linkage);
}
-
- Publish(_loadMetadata);
}
public override Image GetImage(IIconProvider iconProvider) =>
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewClassBasedProcessTask.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewClassBasedProcessTask.cs
index b4afaa4220..75c642a343 100644
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewClassBasedProcessTask.cs
+++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewClassBasedProcessTask.cs
@@ -82,7 +82,7 @@ public override void Execute()
newTask.CreateArgumentsForClassIfNotExists(_type);
- Publish(_loadMetadata);
+ Publish(newTask);
Activate(newTask);
}
}
\ No newline at end of file
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewExtractionConfigurationForProject.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewExtractionConfigurationForProject.cs
index f5b4713d8e..1bbdd5436f 100644
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewExtractionConfigurationForProject.cs
+++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandCreateNewExtractionConfigurationForProject.cs
@@ -141,8 +141,8 @@ public override void Execute()
}
//refresh the project
- Publish(p);
- Activate(newConfig);
+ Publish(newConfig);
+ //Activate(newConfig);
Emphasise(newConfig);
}
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandDelete.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandDelete.cs
index fe08244b50..10bd6e684a 100644
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandDelete.cs
+++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandDelete.cs
@@ -99,6 +99,8 @@ private void ExecuteImpl()
{
case 1:
BasicActivator.DeleteWithConfirmation(_deletables[0]);
+ var x = (IMapsDirectlyToDatabaseTable)_deletables[0];
+ BasicActivator.Publish((IMapsDirectlyToDatabaseTable)_deletables[0]);
return;
case <= 0:
return;
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs
index 05a86e1e77..117920eff9 100644
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs
+++ b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandPerformRegexRedactionOnCatalogue.cs
@@ -84,7 +84,7 @@ public override void Execute()
var dt = new DataTable();
dt.BeginLoadData();
- var conn = _server.GetConnection();
+ using var conn = _server.GetConnection();
conn.Open();
using (var cmd = _server.GetCommand(sql, conn))
{
diff --git a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSimilar.cs b/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSimilar.cs
deleted file mode 100644
index 1cbc1607ff..0000000000
--- a/Rdmp.Core/CommandExecution/AtomicCommands/ExecuteCommandSimilar.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) The University of Dundee 2018-2019
-// This file is part of the Research Data Management Platform (RDMP).
-// RDMP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-// RDMP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License along with RDMP. If not, see .
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Rdmp.Core.Curation.Data;
-using Rdmp.Core.MapsDirectlyToDatabaseTable;
-using Rdmp.Core.QueryBuilding;
-
-namespace Rdmp.Core.CommandExecution.AtomicCommands;
-
-///
-/// Find similar objects to an example e.g. all CHI columns in all datasets. Optionally finds those with important differences only
-/// e.g. data type is different
-///
-public sealed class ExecuteCommandSimilar : BasicCommandExecution
-{
- private readonly IMapsDirectlyToDatabaseTable _to;
- private readonly bool _butDifferent;
-
- ///
- /// Collection of all Types where finding differences between instances is supported by
- ///
- ///
- private readonly Type[] _diffSupportedTypes = { typeof(ColumnInfo) };
-
- private IReadOnlyCollection _matched;
-
-
- ///
- /// The objects matched by the command (similar or different objects)
- ///
- public IReadOnlyCollection Matched
- {
- get { return _matched ??= FetchMatches(); }
- }
-
- ///
- /// Set to true to make command show similar objects in interactive
- ///
- internal bool GoTo { get; init; }
-
- public ExecuteCommandSimilar(IBasicActivateItems activator,
- [DemandsInitialization("An object for which you want to find similar objects")]
- IMapsDirectlyToDatabaseTable to,
- [DemandsInitialization(
- "True to show only objects that are similar (e.g. same name) but different (e.g. different data type)")]
- bool butDifferent) : base(activator)
- {
- _to = to;
- _butDifferent = butDifferent;
-
- if (_butDifferent && !_diffSupportedTypes.Contains(_to.GetType()))
- SetImpossible($"Differencing is not supported on {_to.GetType().Name}");
-
- Weight = 50.3f;
- }
-
- public override void Execute()
- {
- FetchMatches();
-
- if (IsImpossible)
- {
- BasicActivator.Show("No Matches", ReasonCommandImpossible);
- return;
- }
-
- if (!BasicActivator.IsInteractive && GoTo)
- throw new Exception(
- $"GoTo property is true on {nameof(ExecuteCommandSimilar)} but activator is not interactive");
-
- if (GoTo)
- {
- var selected = BasicActivator.SelectOne("Similar Objects", Matched.ToArray(), null, true);
- if (selected != null) Emphasise(selected);
- }
- else
- {
- BasicActivator.Show(string.Join(Environment.NewLine,
- Matched.ToArray().Select(ExecuteCommandDescribe.Describe)));
- }
- }
-
- private static readonly IReadOnlyCollection Empty =
- Enumerable.Empty().ToList().AsReadOnly();
-
- public IReadOnlyCollection FetchMatches()
- {
- if (_matched is not null) return _matched;
-
- try
- {
- var others = BasicActivator.CoreChildProvider.GetAllObjects(_to.GetType(), true).Where(IsSimilar)
- .Where(Include).ToList().AsReadOnly();
- if (others.Count == 0)
- SetImpossible(_butDifferent
- ? "There are no alternate column specifications of this column"
- : "There are no Similar objects");
- return others;
- }
- catch (Exception ex)
- {
- SetImpossible($"Error finding Similar:{ex.Message}");
- return Empty;
- }
- }
-
- public override string GetCommandHelp() =>
- _butDifferent
- ? "Find objects with the same name but different implementation (e.g. different column data type)"
- : "Find other objects with the same or similar name to this";
-
- private bool IsSimilar(IMapsDirectlyToDatabaseTable other)
- {
- // objects are not similar to themselves!
- return !Equals(_to, other) && _to switch
- {
- INamed named when other is INamed otherNamed => SimilarWord(named.Name, otherNamed.Name,
- StringComparison.CurrentCultureIgnoreCase),
- IColumn col when other is IColumn otherCol => SimilarWord(col.SelectSQL, otherCol.SelectSQL,
- StringComparison.CurrentCultureIgnoreCase) || string.Equals(col.Alias, otherCol.Alias,
- StringComparison.CurrentCultureIgnoreCase),
- _ => false
- };
- }
-
- private static readonly char[] TrimChars = { ' ', '[', ']', '\'', '"', '`' };
-
- private static bool SimilarWord(string name1, string name2, StringComparison comparisonType) =>
- !string.IsNullOrWhiteSpace(name1) && !string.IsNullOrWhiteSpace(name2) && string.Equals(
- name1[Math.Max(0, name1.LastIndexOf('.'))..].Trim(TrimChars),
- name2[Math.Max(0, name2.LastIndexOf('.'))..].Trim(TrimChars),
- comparisonType);
-
- private bool Include(IMapsDirectlyToDatabaseTable arg)
- {
- // if we don't care that they are different then return true
- if (!_butDifferent)
- return true;
-
- // or they are different
- if (_to is ColumnInfo col && arg is ColumnInfo otherCol)
- return
- !string.Equals(col.Data_type, otherCol.Data_type) || !string.Equals(col.Collation, otherCol.Collation);
-
- // WHEN ADDING NEW TYPES add the Type to _diffSupportedTypes
-
- return false;
- }
-}
\ No newline at end of file
diff --git a/Rdmp.Core/CommandExecution/BasicActivateItems.cs b/Rdmp.Core/CommandExecution/BasicActivateItems.cs
index e0583256f6..515f36c179 100644
--- a/Rdmp.Core/CommandExecution/BasicActivateItems.cs
+++ b/Rdmp.Core/CommandExecution/BasicActivateItems.cs
@@ -142,13 +142,11 @@ public BasicActivateItems(IRDMPPlatformRepositoryServiceLocator repositoryLocato
CoreIconProvider = new DataExportIconProvider(repositoryLocator, PluginUserInterfaces.ToArray());
}
- protected virtual ICoreChildProvider GetChildProvider()
+ protected virtual ICoreChildProvider GetChildProvider(bool force=false)
{
- // Build new CoreChildProvider in a temp then update to it to avoid stale references
- ICoreChildProvider temp = null;
-
- //prefer a linked repository with both
- if (RepositoryLocator.DataExportRepository != null)
+ if (CoreChildProvider is null || force)
+ {
+ ICoreChildProvider temp = null;
try
{
temp = new DataExportChildProvider(RepositoryLocator, PluginUserInterfaces.ToArray(),
@@ -158,20 +156,12 @@ protected virtual ICoreChildProvider GetChildProvider()
{
ShowException("Error constructing DataExportChildProvider", e);
}
-
- //there was an error generating a data export repository or there was no repository specified
-
- //so just create a catalogue one
- temp ??= new CatalogueChildProvider(RepositoryLocator.CatalogueRepository, PluginUserInterfaces.ToArray(),
- GlobalErrorCheckNotifier, CoreChildProvider as CatalogueChildProvider);
-
- // first time
- if (CoreChildProvider == null)
+ temp ??= new CatalogueChildProvider(RepositoryLocator.CatalogueRepository, PluginUserInterfaces.ToArray(),
+ GlobalErrorCheckNotifier, CoreChildProvider as CatalogueChildProvider);
CoreChildProvider = temp;
- else
- CoreChildProvider.UpdateTo(temp);
-
+ }
return CoreChildProvider;
+
}
private void ConstructPluginChildProviders()
@@ -478,7 +468,6 @@ deletable is IDeletableWithCustomMessage customMessageDeletable
if (deletable is IMasqueradeAs masqueradeAs)
databaseObject ??= masqueradeAs.MasqueradingAs() as DatabaseEntity;
-
return databaseObject == null
? throw new NotSupportedException(
$"IDeletable {deletable} was not a DatabaseObject and it did not have a Parent in its tree which was a DatabaseObject (DescendancyList)")
@@ -530,10 +519,11 @@ protected abstract bool
///
public virtual void Publish(IMapsDirectlyToDatabaseTable databaseEntity)
{
- if (!HardRefresh && UserSettings.SelectiveRefresh && CoreChildProvider.SelectiveRefresh(databaseEntity)) return;
+ //if (!HardRefresh && UserSettings.SelectiveRefresh && CoreChildProvider.SelectiveRefresh(databaseEntity)) return;
+ if (!HardRefresh && CoreChildProvider.SelectiveRefresh(databaseEntity)) return;
- var fresh = GetChildProvider();
- CoreChildProvider.UpdateTo(fresh);
+ var fresh = GetChildProvider(true);//don't know what to do with Entity, so start fresh
+ CoreChildProvider = fresh;
HardRefresh = false;
}
diff --git a/Rdmp.Core/CommandExecution/GoToCommandFactory.cs b/Rdmp.Core/CommandExecution/GoToCommandFactory.cs
index 4852d7589c..b2d71b7b91 100644
--- a/Rdmp.Core/CommandExecution/GoToCommandFactory.cs
+++ b/Rdmp.Core/CommandExecution/GoToCommandFactory.cs
@@ -62,9 +62,6 @@ public IEnumerable GetCommands(object forObject)
if (SupportsReplacement(forObject))
yield return new ExecuteCommandShow(_activator, () => GetReplacementIfAny(mt))
{ OverrideCommandName = "Replacement" };
-
-
- yield return new ExecuteCommandSimilar(_activator, mt, false) { GoTo = true };
}
// cic => associated projects
@@ -83,13 +80,6 @@ public IEnumerable GetCommands(object forObject)
if (Is(forObject, out ColumnInfo columnInfo))
{
- yield return new ExecuteCommandSimilar(_activator, columnInfo, true)
- {
- OverrideCommandName = "Different",
- GoTo = true,
- OverrideIcon = GetImage(RDMPConcept.ColumnInfo)
- };
-
yield return new ExecuteCommandShow(_activator, columnInfo.TableInfo_ID, typeof(TableInfo))
{
OverrideCommandName = "Table Info",
diff --git a/Rdmp.Core/CommandLine/DatabaseCreation/ExampleDatasetsCreation.cs b/Rdmp.Core/CommandLine/DatabaseCreation/ExampleDatasetsCreation.cs
index 660f701c8d..f4bec5e47e 100644
--- a/Rdmp.Core/CommandLine/DatabaseCreation/ExampleDatasetsCreation.cs
+++ b/Rdmp.Core/CommandLine/DatabaseCreation/ExampleDatasetsCreation.cs
@@ -287,7 +287,7 @@ private void ReleaseAllConfigurations(ICheckNotifier notifier,
Pipeline = releasePipeline.ID.ToString()
};
- var runnerRelease = new ReleaseRunner(_activator,optsRelease);
+ var runnerRelease = new ReleaseRunner(_activator, optsRelease);
runnerRelease.Run(_repos, ThrowImmediatelyDataLoadEventListener.Quiet, notifier,
new GracefulCancellationToken());
}
@@ -430,13 +430,19 @@ private CohortIdentificationConfiguration CreateCohortIdentificationConfiguratio
ac.Name = $"People with {inclusionFilter1.Name}";
ac.RootFilterContainer_ID = whereContainer.ID;
cic.EnsureNamingConvention(ac); //this will put cicx at the front and cause implicit SaveToDatabase
-
var filterImporter = new FilterImporter(new AggregateFilterFactory(_repos.CatalogueRepository), null);
var cloneFilter = filterImporter.ImportFilter(whereContainer, inclusionFilter1, null);
whereContainer.AddChild(cloneFilter);
- return cic;
+ var x = _activator.CoreChildProvider.GetAllChildrenRecursively(container).OfType();
+ _activator.CoreChildProvider.SelectiveRefresh(ac);
+ _activator.CoreChildProvider.SelectiveRefresh(container);
+ _activator.CoreChildProvider.SelectiveRefresh(cic);
+ container = _repos.CatalogueRepository.GetObjectByID(container.ID);
+ var y = _activator.CoreChildProvider.GetAllChildrenRecursively(container).OfType();
+ var z = _activator.RepositoryLocator.CatalogueRepository.GetAllObjects();
+ return _repos.CatalogueRepository.GetObjectByID(cic.ID);
}
private IFilter CreateFilter(AggregateConfiguration graph, string name, string whereSql)
@@ -452,7 +458,7 @@ private IFilter CreateFilter(AggregateConfiguration graph, string name, string w
{
container = (AggregateFilterContainer)graph.RootFilterContainer;
}
-
+ _activator.CoreChildProvider.SelectiveRefresh(container);
var filter = new AggregateFilter(_repos.CatalogueRepository, name, container)
{
WhereSQL = whereSql
@@ -519,7 +525,7 @@ private IFilter CreateFilter(ICatalogue cata, string name, string parentExtracti
var parameterCreator = new ParameterCreator(filter.GetFilterFactory(), null, null);
parameterCreator.CreateAll(filter, null);
-
+ _activator.CoreChildProvider.SelectiveRefresh(filter);
return filter;
}
@@ -561,7 +567,7 @@ private AggregateConfiguration CreateGraph(ICatalogue cata, string name, string
ac.PivotOnDimensionID = otherDimension.ID;
ac.SaveToDatabase();
}
-
+ _activator.CoreChildProvider.SelectiveRefresh(ac);
return ac;
}
@@ -666,7 +672,7 @@ private ICatalogue ImportCatalogue(ITableInfo ti)
new ExtractableDataSet(_repos.DataExportRepository, cata);
}
-
+ _activator.CoreChildProvider.SelectiveRefresh(cata);
return cata;
}
diff --git a/Rdmp.Core/Curation/Data/Aggregation/AggregateConfiguration.cs b/Rdmp.Core/Curation/Data/Aggregation/AggregateConfiguration.cs
index 4ff492e4a7..95980cb456 100644
--- a/Rdmp.Core/Curation/Data/Aggregation/AggregateConfiguration.cs
+++ b/Rdmp.Core/Curation/Data/Aggregation/AggregateConfiguration.cs
@@ -579,6 +579,7 @@ public void Check(ICheckNotifier notifier)
"Too many columns, You can only have a maximum of 2 columns in any graph (plus a count column). These are: \r\n 1. The time axis (if any) \r\n 2. The pivot column (if any)");
if (AggregateDimensions.Length == 2 && !PivotOnDimensionID.HasValue)
+
throw new QueryBuildingException("In order to have 2 columns, one must be selected as a pivot");
try
diff --git a/Rdmp.Core/Curation/Data/DataLoad/ANOTable.cs b/Rdmp.Core/Curation/Data/DataLoad/ANOTable.cs
index c7b4054672..9c45fa73eb 100644
--- a/Rdmp.Core/Curation/Data/DataLoad/ANOTable.cs
+++ b/Rdmp.Core/Curation/Data/DataLoad/ANOTable.cs
@@ -363,6 +363,10 @@ CONSTRAINT PK_{TableName} PRIMARY KEY CLUSTERED
CheckResult.Fail, e));
return;
}
+ finally
+ {
+ if (forceConnection == null) con.Close();
+ }
}
try
diff --git a/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs b/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs
index 479746a5ae..d03a6004b0 100644
--- a/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs
+++ b/Rdmp.Core/Curation/Data/DataLoad/LoadMetadata.cs
@@ -308,10 +308,11 @@ internal LoadMetadata(ShareManager shareManager, ShareDefinition shareDefinition
shareManager.UpsertAndHydrate(this, shareDefinition);
}
- public void LinkToCatalogue(ICatalogue catalogue)
+ public LoadMetadataCatalogueLinkage LinkToCatalogue(ICatalogue catalogue)
{
var linkage = new LoadMetadataCatalogueLinkage(CatalogueRepository, this, catalogue);
linkage.SaveToDatabase();
+ return linkage;
}
public void UnlinkFromCatalogue(ICatalogue catalogue)
diff --git a/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs b/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs
index a6df72f990..b82f87f858 100644
--- a/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs
+++ b/Rdmp.Core/Curation/DataHelper/RegexRedaction/RegexRedactionHelper.cs
@@ -152,7 +152,7 @@ public static void DoJoinUpdate(ColumnInfo column, DiscoveredTable _discoveredTa
}
var sql = updateHelper.BuildUpdate(_discoveredTable, redactionTable, sqlLines);
- var conn = _server.GetConnection();
+ using var conn = _server.GetConnection();
conn.Open();
using (var cmd = _server.GetCommand(sql, conn))
{
diff --git a/Rdmp.Core/Curation/KeywordHelp.txt b/Rdmp.Core/Curation/KeywordHelp.txt
index aa5a3742b6..0cebc33886 100644
--- a/Rdmp.Core/Curation/KeywordHelp.txt
+++ b/Rdmp.Core/Curation/KeywordHelp.txt
@@ -61,6 +61,7 @@ idxGovernancePeriodNameMustBeUnique:Prevents you creating two or more Governance
idx_ANOTableNamesMustBeUnique:Prevents you creating two or more ANOTables with the same name
ix_suffixMustBeUnique:Prevents you using the same suffix for two or more ANOTables
ix_ConceptNamesMustBeUnique:Prevents you naming two StandardRegex the same name (ConceptName)
+IX_MSchange_tracking_history_start_time:changes tracking history start time
ix_PreventDuplicateParameterNamesOnSameEntity:Prevents the same SQL parameter being declared twice on a given table that is ICollectSqlParameters e.g. TableInfo cannot have two global parameters with the same name @bob
ix_PluginNamesMustBeUnique:Prevents you uploading two copies of the same plugin e.g. MyPlugin.zip, if you want to update your plugin you should delete the old one
ix_CataloguesCanOnlyBeLockedByOneAutomationJobAtATime:Prevents the Automation server from performing conflicting operations on a Catalogue e.g. trying to DQE it while also loading it.
diff --git a/Rdmp.Core/DataExport/DataExtraction/Pipeline/ExtractionPipelineUseCase.cs b/Rdmp.Core/DataExport/DataExtraction/Pipeline/ExtractionPipelineUseCase.cs
index faa03834e6..892c68a193 100644
--- a/Rdmp.Core/DataExport/DataExtraction/Pipeline/ExtractionPipelineUseCase.cs
+++ b/Rdmp.Core/DataExport/DataExtraction/Pipeline/ExtractionPipelineUseCase.cs
@@ -346,7 +346,7 @@ private void WriteMetadata(IDataLoadEventListener listener)
}
}
- private ExtractionPipelineUseCase()
+ public ExtractionPipelineUseCase()
: base(new Type[]
{
typeof(IExtractCommand),
diff --git a/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs b/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs
index 64b074e055..3818bdff92 100644
--- a/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs
+++ b/Rdmp.Core/DataLoad/Engine/Pipeline/Components/Anonymisation/ANOTransformer.cs
@@ -122,7 +122,6 @@ private DataTable GetSubstitutionsForANOEquivalents(DataTable table, bool previe
{
using var con = (SqlConnection)_server.GetConnection();
con.InfoMessage += _con_InfoMessage;
-
if (table.Rows.Count == 0)
return table;
try
@@ -162,7 +161,6 @@ private DataTable GetSubstitutionsForANOEquivalents(DataTable table, bool previe
CommandTimeout = 500,
Transaction = transaction
};
-
cmdSubstituteIdentifiers.Parameters.Add("@batch", SqlDbType.Structured);
cmdSubstituteIdentifiers.Parameters.Add("@tableName", SqlDbType.VarChar, 500);
cmdSubstituteIdentifiers.Parameters.Add("@numberOfIntegersToUseInAnonymousRepresentation", SqlDbType.Int);
@@ -179,7 +177,6 @@ private DataTable GetSubstitutionsForANOEquivalents(DataTable table, bool previe
cmdSubstituteIdentifiers.Parameters["@numberOfCharactersToUseInAnonymousRepresentation"].Value =
_anoTable.NumberOfCharactersToUseInAnonymousRepresentation;
cmdSubstituteIdentifiers.Parameters["@suffix"].Value = _anoTable.Suffix;
-
var da = new SqlDataAdapter(cmdSubstituteIdentifiers);
var dtToReturn = new DataTable();
dtToReturn.BeginLoadData();
diff --git a/Rdmp.Core/DataLoad/Engine/Pipeline/UploadFileUseCase.cs b/Rdmp.Core/DataLoad/Engine/Pipeline/UploadFileUseCase.cs
index 26e94f5570..a09c65c587 100644
--- a/Rdmp.Core/DataLoad/Engine/Pipeline/UploadFileUseCase.cs
+++ b/Rdmp.Core/DataLoad/Engine/Pipeline/UploadFileUseCase.cs
@@ -36,7 +36,7 @@ protected override IDataFlowPipelineContext GenerateContextImpl()
return context;
}
- private UploadFileUseCase() : base(new[]
+ public UploadFileUseCase() : base(new[]
{
typeof(FlatFileToLoad),
typeof(DiscoveredDatabase),
diff --git a/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs b/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs
index d73ff6a91d..ff726b7168 100644
--- a/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs
+++ b/Rdmp.Core/DataLoad/Modules/Mutilators/RegexRedactionMutilator.cs
@@ -98,7 +98,7 @@ protected override void MutilateTable(IDataLoadJob job, ITableInfo tableInfo, Di
";
var dt = new DataTable();
dt.BeginLoadData();
- var conn = table.Database.Server.GetConnection();
+ using var conn = table.Database.Server.GetConnection();
conn.Open();
using (var cmd = table.Database.Server.GetCommand(sql, conn))
{
diff --git a/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs b/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs
index d831914191..bc61f8b424 100644
--- a/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs
+++ b/Rdmp.Core/MapsDirectlyToDatabaseTable/TableRepository.cs
@@ -17,6 +17,7 @@
using FAnsi;
using FAnsi.Connections;
using FAnsi.Discovery;
+using Microsoft.Data.SqlClient;
using NLog;
using Rdmp.Core.MapsDirectlyToDatabaseTable.Injection;
using Rdmp.Core.MapsDirectlyToDatabaseTable.Revertable;
@@ -273,12 +274,14 @@ public T[] GetAllObjects(string whereSQL) where T : IMapsDirectlyToDatabaseTa
var toReturn = new List();
using var opener = GetConnection();
+
var selectCommand = DatabaseCommandHelper.GetCommand($"SELECT * FROM {typename} {whereSQL ?? ""}",
opener.Connection, opener.Transaction);
using var r = selectCommand.ExecuteReader();
while (r.Read())
toReturn.Add(ConstructEntity(r));
+ r.Close();
return toReturn.ToArray();
}
diff --git a/Rdmp.Core/Providers/CatalogueChildProvider.cs b/Rdmp.Core/Providers/CatalogueChildProvider.cs
index 83faac340a..b002fa2882 100644
--- a/Rdmp.Core/Providers/CatalogueChildProvider.cs
+++ b/Rdmp.Core/Providers/CatalogueChildProvider.cs
@@ -11,6 +11,10 @@
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
+using NPOI.OpenXmlFormats.Dml;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Rdmp.Core.Caching.Pipeline;
+using Rdmp.Core.CohortCommitting.Pipeline;
using Rdmp.Core.Curation.Data;
using Rdmp.Core.Curation.Data.Aggregation;
using Rdmp.Core.Curation.Data.Cache;
@@ -23,6 +27,10 @@
using Rdmp.Core.Curation.Data.Pipelines;
using Rdmp.Core.Curation.Data.Remoting;
using Rdmp.Core.Curation.DataHelper.RegexRedaction;
+using Rdmp.Core.DataExport.Data;
+using Rdmp.Core.DataExport.DataExtraction.Pipeline;
+using Rdmp.Core.DataExport.DataRelease.Pipeline;
+using Rdmp.Core.DataLoad.Engine.Pipeline;
using Rdmp.Core.MapsDirectlyToDatabaseTable;
using Rdmp.Core.Providers.Nodes;
using Rdmp.Core.Providers.Nodes.CohortNodes;
@@ -55,168 +63,306 @@ namespace Rdmp.Core.Providers;
public class CatalogueChildProvider : ICoreChildProvider
{
//Load System
- public LoadMetadata[] AllLoadMetadatas { get; set; }
- public LoadMetadataCatalogueLinkage[] AllLoadMetadataCatalogueLinkages { get; set; }
+ LazyWithReset _lazyAllLoadMetadatas = new(() => []);
+ public LoadMetadata[] AllLoadMetadatas { get => _lazyAllLoadMetadatas.Value; }
- private LoadMetadataCatalogueLinkage[] AllLoadMetadataLinkage { get; set; }
- public ProcessTask[] AllProcessTasks { get; set; }
- public ProcessTaskArgument[] AllProcessTasksArguments { get; set; }
+ LazyWithReset _lazyAllLoadMetadataCatalogueLinkages = new(() => []);
+ public LoadMetadataCatalogueLinkage[] AllLoadMetadataCatalogueLinkages { get => _lazyAllLoadMetadataCatalogueLinkages.Value; }
- public LoadProgress[] AllLoadProgresses { get; set; }
- public CacheProgress[] AllCacheProgresses { get; set; }
- public PermissionWindow[] AllPermissionWindows { get; set; }
+ LazyWithReset _lazyAllLoadMetadataLinkage = new(() => []);
+ private LoadMetadataCatalogueLinkage[] AllLoadMetadataLinkage { get => _lazyAllLoadMetadataLinkage.Value; }
+
+ LazyWithReset _lazyAllProcessTasks = new(() => []);
+ public ProcessTask[] AllProcessTasks { get => _lazyAllProcessTasks.Value; }
+
+ LazyWithReset _lazyAllProcessTasksArguments = new(() => []);
+ public ProcessTaskArgument[] AllProcessTasksArguments { get => _lazyAllProcessTasksArguments.Value; }
+
+ LazyWithReset _lazyAllLoadProgress = new(() => []);
+ public LoadProgress[] AllLoadProgresses { get => _lazyAllLoadProgress.Value; }
+
+ LazyWithReset _lazyAllCacheProgresses = new(() => []);
+ public CacheProgress[] AllCacheProgresses { get => _lazyAllCacheProgresses.Value; }
+
+ LazyWithReset _lazyAllPermissionWindows = new(() => []);
+ public PermissionWindow[] AllPermissionWindows { get => _lazyAllPermissionWindows.Value; }
//Catalogue side of things
- public Catalogue[] AllCatalogues { get; set; }
- public Curation.Data.Dataset[] AllDatasets { get; set; }
- public Dictionary AllCataloguesDictionary { get; private set; }
+ LazyWithReset _lazyAllCatalogues = new(() => []);
+ public Catalogue[] AllCatalogues { get => _lazyAllCatalogues.Value; }
+
+ LazyWithReset _lazyAllDatasets = new(() => []);
+ public Curation.Data.Dataset[] AllDatasets { get => _lazyAllDatasets.Value; }
+
+ LazyWithReset> _lazyAllCataloguesDictionary = new(() => []);
+ public Dictionary AllCataloguesDictionary { get => _lazyAllCataloguesDictionary.Value; }
+
+ LazyWithReset _lazyAllSupportingDocuments = new(() => []);
+ public SupportingDocument[] AllSupportingDocuments { get => _lazyAllSupportingDocuments.Value; }
- public SupportingDocument[] AllSupportingDocuments { get; set; }
- public SupportingSQLTable[] AllSupportingSQL { get; set; }
+ LazyWithReset _lazyAllSupportingSQL = new(() => []);
+ public SupportingSQLTable[] AllSupportingSQL { get => _lazyAllSupportingSQL.Value; }
//tells you the immediate children of a given node. Do not add to this directly instead add using AddToDictionaries unless you want the Key to be an 'on the sly' no known descendency child
- private ConcurrentDictionary