From 0427956e8bb2f5e6f111962016b05f8c7334fee1 Mon Sep 17 00:00:00 2001 From: David Sparer Date: Sat, 3 Nov 2018 10:34:30 -0500 Subject: [PATCH] we can now prevent saving to the database when a save was triggered for a local-only property change this will prevent unnecessary db saves --- .../Config/Connections/CsvConnectionsSaver.cs | 2 +- .../Connections/SaveConnectionsOnEdit.cs | 6 +-- .../Config/Connections/SqlConnectionsSaver.cs | 24 ++++++++- .../Config/Connections/XmlConnectionsSaver.cs | 2 +- .../Config/CredentialRepositoryListSaver.cs | 2 +- mRemoteV1/Config/ISaver.cs | 2 +- .../Connection/AbstractConnectionRecord.cs | 2 +- mRemoteV1/Connection/ConnectionsService.cs | 54 +++++++++++++------ mRemoteV1/Container/ContainerInfo.cs | 14 +++-- 9 files changed, 80 insertions(+), 28 deletions(-) diff --git a/mRemoteV1/Config/Connections/CsvConnectionsSaver.cs b/mRemoteV1/Config/Connections/CsvConnectionsSaver.cs index 28e7b79e2..598cea19f 100644 --- a/mRemoteV1/Config/Connections/CsvConnectionsSaver.cs +++ b/mRemoteV1/Config/Connections/CsvConnectionsSaver.cs @@ -24,7 +24,7 @@ namespace mRemoteNG.Config.Connections _saveFilter = saveFilter; } - public void Save(ConnectionTreeModel connectionTreeModel) + public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "") { var csvConnectionsSerializer = new CsvConnectionsSerializerMremotengFormat(_saveFilter, Runtime.CredentialProviderCatalog); var dataProvider = new FileDataProvider(_connectionFileName); diff --git a/mRemoteV1/Config/Connections/SaveConnectionsOnEdit.cs b/mRemoteV1/Config/Connections/SaveConnectionsOnEdit.cs index 038b7fff9..d36648af3 100644 --- a/mRemoteV1/Config/Connections/SaveConnectionsOnEdit.cs +++ b/mRemoteV1/Config/Connections/SaveConnectionsOnEdit.cs @@ -33,7 +33,7 @@ namespace mRemoteNG.Config.Connections private void ConnectionTreeModelOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs) { - SaveConnectionOnEdit(); + SaveConnectionOnEdit(propertyChangedEventArgs.PropertyName); } private void ConnectionTreeModelOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) @@ -41,14 +41,14 @@ namespace mRemoteNG.Config.Connections SaveConnectionOnEdit(); } - private void SaveConnectionOnEdit() + private void SaveConnectionOnEdit(string propertyName = "") { if (!mRemoteNG.Settings.Default.SaveConnectionsAfterEveryEdit) return; if (FrmMain.Default.IsClosing) return; - _connectionsService.SaveConnectionsAsync(); + _connectionsService.SaveConnectionsAsync(propertyName); } } } diff --git a/mRemoteV1/Config/Connections/SqlConnectionsSaver.cs b/mRemoteV1/Config/Connections/SqlConnectionsSaver.cs index d73f9fa73..5c1b295a6 100644 --- a/mRemoteV1/Config/Connections/SqlConnectionsSaver.cs +++ b/mRemoteV1/Config/Connections/SqlConnectionsSaver.cs @@ -18,6 +18,7 @@ using System.Data.SqlClient; using System.Globalization; using System.Linq; using System.Security; +using mRemoteNG.Connection; namespace mRemoteNG.Config.Connections { @@ -40,12 +41,19 @@ namespace mRemoteNG.Config.Connections _dataProvider = localPropertiesDataProvider.ThrowIfNull(nameof(localPropertiesDataProvider)); } - public void Save(ConnectionTreeModel connectionTreeModel) + public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "") { var rootTreeNode = connectionTreeModel.RootNodes.OfType().First(); UpdateLocalConnectionProperties(rootTreeNode); + if (PropertyIsLocalOnly(propertyNameTrigger)) + { + Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, + $"Property {propertyNameTrigger} is local only. Not saving to database."); + return; + } + if (SqlUserIsReadOnly()) { Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Trying to save connection tree but the SQL read only checkbox is checked, aborting!"); @@ -71,6 +79,20 @@ namespace mRemoteNG.Config.Connections Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved connections to database"); } + /// + /// Determines if a given property name should be only saved + /// locally. + /// + /// + /// The name of the property that triggered the save event + /// + /// + private bool PropertyIsLocalOnly(string property) + { + return property == nameof(ConnectionInfo.OpenConnections) || + property == nameof(ContainerInfo.IsExpanded); + } + private void UpdateLocalConnectionProperties(ContainerInfo rootNode) { var a = rootNode.GetRecursiveChildList().Select(info => new LocalConnectionPropertiesModel diff --git a/mRemoteV1/Config/Connections/XmlConnectionsSaver.cs b/mRemoteV1/Config/Connections/XmlConnectionsSaver.cs index 08fa5c0c0..9e6d90cb0 100644 --- a/mRemoteV1/Config/Connections/XmlConnectionsSaver.cs +++ b/mRemoteV1/Config/Connections/XmlConnectionsSaver.cs @@ -27,7 +27,7 @@ namespace mRemoteNG.Config.Connections _saveFilter = saveFilter; } - public void Save(ConnectionTreeModel connectionTreeModel) + public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "") { try { diff --git a/mRemoteV1/Config/CredentialRepositoryListSaver.cs b/mRemoteV1/Config/CredentialRepositoryListSaver.cs index c5000024c..6200eb729 100644 --- a/mRemoteV1/Config/CredentialRepositoryListSaver.cs +++ b/mRemoteV1/Config/CredentialRepositoryListSaver.cs @@ -18,7 +18,7 @@ namespace mRemoteNG.Config _dataProvider = dataProvider; } - public void Save(IEnumerable repositories) + public void Save(IEnumerable repositories, string propertyNameTrigger = "") { var serializer = new CredentialRepositoryListSerializer(); var data = serializer.Serialize(repositories); diff --git a/mRemoteV1/Config/ISaver.cs b/mRemoteV1/Config/ISaver.cs index cf4caea8d..1f9700be8 100644 --- a/mRemoteV1/Config/ISaver.cs +++ b/mRemoteV1/Config/ISaver.cs @@ -2,6 +2,6 @@ { public interface ISaver { - void Save(T model); + void Save(T model, string propertyNameTrigger = ""); } } \ No newline at end of file diff --git a/mRemoteV1/Connection/AbstractConnectionRecord.cs b/mRemoteV1/Connection/AbstractConnectionRecord.cs index 8020169a4..9a29be75b 100644 --- a/mRemoteV1/Connection/AbstractConnectionRecord.cs +++ b/mRemoteV1/Connection/AbstractConnectionRecord.cs @@ -674,7 +674,7 @@ namespace mRemoteNG.Connection PropertyChanged?.Invoke(sender, new PropertyChangedEventArgs(args.PropertyName)); } - private void SetField(ref T field, T value, string propertyName = null) + protected void SetField(ref T field, T value, string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return; field = value; diff --git a/mRemoteV1/Connection/ConnectionsService.cs b/mRemoteV1/Connection/ConnectionsService.cs index 3042b97d2..93fa7bcc1 100644 --- a/mRemoteV1/Connection/ConnectionsService.cs +++ b/mRemoteV1/Connection/ConnectionsService.cs @@ -16,6 +16,7 @@ using System; using System.IO; using System.Threading; using System.Windows.Forms; +using mRemoteNG.Config; namespace mRemoteNG.Connection { @@ -187,7 +188,17 @@ namespace mRemoteNG.Connection /// /// /// Bypasses safety checks that prevent saving if a connection file isn't loaded. - public void SaveConnections(ConnectionTreeModel connectionTreeModel, bool useDatabase, SaveFilter saveFilter, string connectionFileName, bool forceSave = false) + /// + /// Optional. The name of the property that triggered + /// this save. + /// + public void SaveConnections( + ConnectionTreeModel connectionTreeModel, + bool useDatabase, + SaveFilter saveFilter, + string connectionFileName, + bool forceSave = false, + string propertyNameTrigger = "") { if (connectionTreeModel == null) return; @@ -207,10 +218,13 @@ namespace mRemoteNG.Connection RemoteConnectionsSyncronizer?.Disable(); var previouslyUsingDatabase = UsingDatabase; - if (useDatabase) - new SqlConnectionsSaver(saveFilter, _localConnectionPropertiesSerializer, _localConnectionPropertiesDataProvider).Save(connectionTreeModel); - else - new XmlConnectionsSaver(connectionFileName, saveFilter).Save(connectionTreeModel); + + var saver = useDatabase + ? (ISaver)new SqlConnectionsSaver(saveFilter, _localConnectionPropertiesSerializer, + _localConnectionPropertiesDataProvider) + : new XmlConnectionsSaver(connectionFileName, saveFilter); + + saver.Save(connectionTreeModel, propertyNameTrigger); if (UsingDatabase) LastSqlUpdate = DateTime.Now; @@ -230,7 +244,14 @@ namespace mRemoteNG.Connection } } - public void SaveConnectionsAsync() + /// + /// Save the currently loaded connections asynchronously + /// + /// + /// Optional. The name of the property that triggered + /// this save. + /// + public void SaveConnectionsAsync(string propertyNameTrigger = "") { if (_batchingSaves) { @@ -238,19 +259,22 @@ namespace mRemoteNG.Connection return; } - var t = new Thread(SaveConnectionsBGd); + var t = new Thread(() => + { + lock (SaveLock) + { + SaveConnections( + ConnectionTreeModel, + UsingDatabase, + new SaveFilter(), + ConnectionFileName, + propertyNameTrigger: propertyNameTrigger); + } + }); t.SetApartmentState(ApartmentState.STA); t.Start(); } - private void SaveConnectionsBGd() - { - lock (SaveLock) - { - SaveConnections(); - } - } - public string GetStartupConnectionFileName() { return Settings.Default.LoadConsFromCustomLocation == false diff --git a/mRemoteV1/Container/ContainerInfo.cs b/mRemoteV1/Container/ContainerInfo.cs index c6c6b4c8f..989fc9113 100644 --- a/mRemoteV1/Container/ContainerInfo.cs +++ b/mRemoteV1/Container/ContainerInfo.cs @@ -12,13 +12,19 @@ namespace mRemoteNG.Container [DefaultProperty("Name")] public class ContainerInfo : ConnectionInfo, INotifyCollectionChanged { - [Browsable(false)] + private bool _isExpanded; + + [Browsable(false)] public List Children { get; } = new List(); - [Category(""), Browsable(false), ReadOnly(false), Bindable(false), DefaultValue(""), DesignOnly(false)] - public bool IsExpanded { get; set; } + [Category(""), Browsable(false), ReadOnly(false), Bindable(false), DefaultValue(""), DesignOnly(false)] + public bool IsExpanded + { + get => _isExpanded; + set => SetField(ref _isExpanded, value, "IsExpanded"); + } - [Browsable(false)] + [Browsable(false)] public override bool IsContainer { get { return true; } set {} } public ContainerInfo(string uniqueId)