diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index 75fa9a3a1..42daefc59 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -40,7 +40,7 @@
-
+
diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs
index 79d19cc48..dfa7791c5 100644
--- a/src/Artemis.Core/Constants.cs
+++ b/src/Artemis.Core/Constants.cs
@@ -91,7 +91,7 @@ public static class Constants
///
/// The plugin used by core components of Artemis
///
- public static readonly Plugin CorePlugin = new(CorePluginInfo, new DirectoryInfo(ApplicationFolder), new PluginEntity(){Id = CorePluginInfo.Guid}, false);
+ public static readonly Plugin CorePlugin = new(CorePluginInfo, new DirectoryInfo(ApplicationFolder), new PluginEntity(){PluginGuid = CorePluginInfo.Guid}, false);
///
/// A read-only collection containing all primitive numeric types
diff --git a/src/Artemis.Core/Plugins/Plugin.cs b/src/Artemis.Core/Plugins/Plugin.cs
index 2b5ce51d1..5eacf18f0 100644
--- a/src/Artemis.Core/Plugins/Plugin.cs
+++ b/src/Artemis.Core/Plugins/Plugin.cs
@@ -309,13 +309,7 @@ public class Plugin : CorePropertyChanged, IDisposable
{
FeatureRemoved?.Invoke(this, e);
}
-
- internal void ApplyToEntity()
- {
- Entity.Id = Guid;
- Entity.IsEnabled = IsEnabled;
- }
-
+
internal void AddFeature(PluginFeatureInfo featureInfo)
{
if (featureInfo.Plugin != this)
diff --git a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
index e3510a58e..8f14d542f 100644
--- a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
+++ b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
@@ -94,7 +94,7 @@ public class PluginSetting : CorePropertyChanged, IPluginSetting
return;
_pluginSettingEntity.Value = CoreJson.Serialize(Value);
- _pluginRepository.SaveChanges();
+ _pluginRepository.SaveSetting(_pluginSettingEntity);
OnSettingSaved();
}
diff --git a/src/Artemis.Core/Plugins/Settings/PluginSettings.cs b/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
index 89c1a10ea..811dcf817 100644
--- a/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
+++ b/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
@@ -31,10 +31,13 @@ public class PluginSettings
/// Gets the setting with the provided name. If the setting does not exist yet, it is created.
///
/// The type of the setting, can be any serializable type
- /// The name of the setting
+ /// The name of the setting, may not be longer than 128 characters
/// The default value to use if the setting does not exist yet
public PluginSetting GetSetting(string name, T? defaultValue = default)
{
+ if (name.Length > 128)
+ throw new ArtemisCoreException("Setting name cannot be longer than 128 characters");
+
lock (_settingEntities)
{
// Return cached value if available
@@ -51,7 +54,7 @@ public class PluginSettings
PluginGuid = Plugin.Guid,
Value = CoreJson.Serialize(defaultValue)
};
- _pluginRepository.AddSetting(settingEntity);
+ _pluginRepository.SaveSetting(settingEntity);
}
PluginSetting pluginSetting = new(_pluginRepository, settingEntity);
diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs
index 46399722e..da81a82a6 100644
--- a/src/Artemis.Core/Services/DeviceService.cs
+++ b/src/Artemis.Core/Services/DeviceService.cs
@@ -202,7 +202,7 @@ internal class DeviceService : IDeviceService
_enabledDevices.Add(device);
device.IsEnabled = true;
device.Save();
- _deviceRepository.SaveChanges();
+ _deviceRepository.Save(device.DeviceEntity);
OnDeviceEnabled(new DeviceEventArgs(device));
UpdateLeds();
@@ -217,7 +217,7 @@ internal class DeviceService : IDeviceService
_enabledDevices.Remove(device);
device.IsEnabled = false;
device.Save();
- _deviceRepository.SaveChanges();
+ _deviceRepository.Save(device.DeviceEntity);
OnDeviceDisabled(new DeviceEventArgs(device));
UpdateLeds();
@@ -227,7 +227,7 @@ internal class DeviceService : IDeviceService
public void SaveDevice(ArtemisDevice artemisDevice)
{
artemisDevice.Save();
- _deviceRepository.SaveChanges();
+ _deviceRepository.Save(artemisDevice.DeviceEntity);
UpdateLeds();
}
@@ -236,7 +236,7 @@ internal class DeviceService : IDeviceService
{
foreach (ArtemisDevice artemisDevice in _devices)
artemisDevice.Save();
- _deviceRepository.SaveChanges();
+ _deviceRepository.SaveRange(_devices.Select(d => d.DeviceEntity));
UpdateLeds();
}
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 5b31b31d9..62bc658ac 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -372,12 +372,12 @@ internal class PluginManagementService : IPluginManagementService
}
// Load the entity and fall back on creating a new one
- PluginEntity? entity = _pluginRepository.GetPluginByGuid(pluginInfo.Guid);
+ PluginEntity? entity = _pluginRepository.GetPluginByPluginGuid(pluginInfo.Guid);
bool loadedFromStorage = entity != null;
if (entity == null)
{
- entity = new PluginEntity {Id = pluginInfo.Guid};
- _pluginRepository.AddPlugin(entity);
+ entity = new PluginEntity {PluginGuid = pluginInfo.Guid};
+ _pluginRepository.SavePlugin(entity);
}
Plugin plugin = new(pluginInfo, directory, entity, loadedFromStorage);
@@ -815,7 +815,7 @@ internal class PluginManagementService : IPluginManagementService
plugin.Entity.Features.Add(featureInfo.Instance!.Entity);
}
- _pluginRepository.SaveChanges();
+ _pluginRepository.SavePlugin(plugin.Entity);
}
#endregion
diff --git a/src/Artemis.Core/Services/SettingsService.cs b/src/Artemis.Core/Services/SettingsService.cs
index 96719eae0..a3cf4c030 100644
--- a/src/Artemis.Core/Services/SettingsService.cs
+++ b/src/Artemis.Core/Services/SettingsService.cs
@@ -34,7 +34,7 @@ public interface ISettingsService : IProtectedArtemisService
/// Gets the setting with the provided name. If the setting does not exist yet, it is created.
///
/// The type of the setting, can be any serializable type
- /// The name of the setting
+ /// The name of the setting, may not be longer than 128 characters
/// The default value to use if the setting does not exist yet
///
PluginSetting GetSetting(string name, T? defaultValue = default);
diff --git a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
index 47766f5bb..c8a5f8435 100644
--- a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
@@ -54,13 +54,7 @@ public interface IProfileService : IArtemisService
///
/// The profile configuration of the profile to activate.
void DeactivateProfile(ProfileConfiguration profileConfiguration);
-
- ///
- /// Permanently deletes the profile of the given .
- ///
- /// The profile configuration of the profile to delete.
- void DeleteProfile(ProfileConfiguration profileConfiguration);
-
+
///
/// Saves the provided and it's s but not the
/// s themselves.
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index 423f50797..6b9889e19 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -22,6 +22,7 @@ internal class ProfileService : IProfileService
{
private readonly ILogger _logger;
private readonly IProfileCategoryRepository _profileCategoryRepository;
+ private readonly IProfileRepository _profileRepository;
private readonly IPluginManagementService _pluginManagementService;
private readonly IDeviceService _deviceService;
private readonly List _pendingKeyboardEvents = new();
@@ -34,6 +35,7 @@ internal class ProfileService : IProfileService
public ProfileService(ILogger logger,
IProfileCategoryRepository profileCategoryRepository,
+ IProfileRepository profileRepository,
IPluginManagementService pluginManagementService,
IInputService inputService,
IDeviceService deviceService,
@@ -41,6 +43,7 @@ internal class ProfileService : IProfileService
{
_logger = logger;
_profileCategoryRepository = profileCategoryRepository;
+ _profileRepository = profileRepository;
_pluginManagementService = pluginManagementService;
_deviceService = deviceService;
_profileMigrators = profileMigrators;
@@ -214,20 +217,7 @@ internal class ProfileService : IProfileService
profileConfiguration.Profile.ShouldDisplay = false;
}
-
- ///
- public void DeleteProfile(ProfileConfiguration profileConfiguration)
- {
- DeactivateProfile(profileConfiguration);
-
- ProfileCategory category = profileConfiguration.Category;
-
- category.RemoveProfileConfiguration(profileConfiguration);
- category.Entity.ProfileConfigurations.Remove(profileConfiguration.Entity);
-
- _profileCategoryRepository.SaveChanges();
- }
-
+
///
public ProfileCategory CreateProfileCategory(string name, bool addToTop = false)
{
@@ -240,6 +230,8 @@ internal class ProfileService : IProfileService
category.Order++;
category.Save();
}
+
+ _profileCategoryRepository.SaveRange(ProfileCategories.Select(c => c.Entity).ToList());
}
else
{
@@ -274,32 +266,32 @@ internal class ProfileService : IProfileService
SaveProfileCategory(category);
return configuration;
}
-
+
///
public void RemoveProfileConfiguration(ProfileConfiguration profileConfiguration)
{
- ProfileCategory category = profileConfiguration.Category;
- category.RemoveProfileConfiguration(profileConfiguration);
-
DeactivateProfile(profileConfiguration);
- SaveProfileCategory(profileConfiguration.Category);
- profileConfiguration.Dispose();
+ ProfileCategory category = profileConfiguration.Category;
+
+ category.RemoveProfileConfiguration(profileConfiguration);
+ category.Save();
+
+ _profileRepository.Remove(profileConfiguration.Entity);
+ _profileCategoryRepository.Save(category.Entity);
}
///
public void SaveProfileCategory(ProfileCategory profileCategory)
{
profileCategory.Save();
- _profileCategoryRepository.SaveChanges();
+ _profileCategoryRepository.Save(profileCategory.Entity);
ProfileCategories = new ReadOnlyCollection(ProfileCategories.OrderBy(c => c.Order).ToList());
}
///
public void SaveProfile(Profile profile, bool includeChildren)
{
- Stopwatch sw = new();
- sw.Start();
_logger.Debug("Updating profile - Saving {Profile}", profile);
profile.Save();
if (includeChildren)
@@ -312,7 +304,7 @@ internal class ProfileService : IProfileService
profile.IsFreshImport = false;
profile.ProfileEntity.IsFreshImport = false;
- SaveProfileCategory(profile.Configuration.Category);
+ _profileRepository.Save(profile.Configuration.Entity);
// If the provided profile is external (cloned or from the workshop?) but it is loaded locally too, reload the local instance
// A bit dodge but it ensures local instances always represent the latest stored version
@@ -320,17 +312,10 @@ internal class ProfileService : IProfileService
.SelectMany(c => c.ProfileConfigurations)
.FirstOrDefault(p => p.Profile != null && p.Profile != profile && p.ProfileId == profile.ProfileEntity.Id);
if (localInstance == null)
- {
- sw.Stop();
- _logger.Debug("Updated profile - Saved {Profile} in {Time}ms", profile, sw.Elapsed.TotalMilliseconds);
return;
- }
DeactivateProfile(localInstance);
ActivateProfile(localInstance);
-
- sw.Stop();
- _logger.Debug("Updated profile - Saved {Profile} in {Time}ms", profile, sw.Elapsed.TotalMilliseconds);
}
///
@@ -393,7 +378,7 @@ internal class ProfileService : IProfileService
JsonObject? profileJson = CoreJson.Deserialize(await profileReader.ReadToEndAsync());
// Before deserializing, apply any pending migrations
- MigrateProfile(configurationJson, profileJson);
+ _profileRepository.MigrateProfile(configurationJson, profileJson);
// Deserialize profile configuration to ProfileConfigurationEntity
ProfileConfigurationEntity? configurationEntity = configurationJson?.Deserialize(Constants.JsonConvertSettings);
@@ -453,7 +438,7 @@ internal class ProfileService : IProfileService
{
ProfileConfiguration imported = await ImportProfile(archiveStream, profileConfiguration.Category, true, true, null, profileConfiguration.Order + 1);
- DeleteProfile(profileConfiguration);
+ RemoveProfileConfiguration(profileConfiguration);
SaveProfileCategory(imported.Category);
return imported;
@@ -479,24 +464,7 @@ internal class ProfileService : IProfileService
{
_pendingKeyboardEvents.Add(e);
}
-
- private void MigrateProfile(JsonObject? configurationJson, JsonObject? profileJson)
- {
- if (configurationJson == null || profileJson == null)
- return;
-
- configurationJson["Version"] ??= 0;
-
- foreach (IProfileMigration profileMigrator in _profileMigrators.OrderBy(m => m.Version))
- {
- if (profileMigrator.Version <= configurationJson["Version"]!.GetValue())
- continue;
-
- profileMigrator.Migrate(configurationJson, profileJson);
- configurationJson["Version"] = profileMigrator.Version;
- }
- }
-
+
///
/// Populates all missing LEDs on all currently active profiles
///
diff --git a/src/Artemis.Storage.Migrator/Artemis.Storage.Migrator.csproj b/src/Artemis.Storage.Legacy/Artemis.Storage.Legacy.csproj
similarity index 78%
rename from src/Artemis.Storage.Migrator/Artemis.Storage.Migrator.csproj
rename to src/Artemis.Storage.Legacy/Artemis.Storage.Legacy.csproj
index dbc3a660d..2da8bd8c3 100644
--- a/src/Artemis.Storage.Migrator/Artemis.Storage.Migrator.csproj
+++ b/src/Artemis.Storage.Legacy/Artemis.Storage.Legacy.csproj
@@ -1,7 +1,6 @@
- Exe
net8.0
enable
enable
@@ -13,8 +12,8 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/General/QueuedActionEntity.cs b/src/Artemis.Storage.Legacy/Entities/General/QueuedActionEntity.cs
similarity index 76%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/General/QueuedActionEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/General/QueuedActionEntity.cs
index 8244c57ec..90770d565 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/General/QueuedActionEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/General/QueuedActionEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.General;
+namespace Artemis.Storage.Legacy.Entities.General;
-public class QueuedActionEntity
+internal class QueuedActionEntity
{
public QueuedActionEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/General/ReleaseEntity.cs b/src/Artemis.Storage.Legacy/Entities/General/ReleaseEntity.cs
similarity index 82%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/General/ReleaseEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/General/ReleaseEntity.cs
index a0d9795bf..a8aea26a8 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/General/ReleaseEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/General/ReleaseEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.General;
+namespace Artemis.Storage.Legacy.Entities.General;
-public class ReleaseEntity
+internal class ReleaseEntity
{
public Guid Id { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/General/ScriptConfigurationEntity.cs b/src/Artemis.Storage.Legacy/Entities/General/ScriptConfigurationEntity.cs
similarity index 66%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/General/ScriptConfigurationEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/General/ScriptConfigurationEntity.cs
index 4c1743fb6..94fce07e4 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/General/ScriptConfigurationEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/General/ScriptConfigurationEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.General;
+namespace Artemis.Storage.Legacy.Entities.General;
-public class ScriptConfigurationEntity
+internal class ScriptConfigurationEntity
{
public Guid Id { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Plugins/PluginEntity.cs b/src/Artemis.Storage.Legacy/Entities/Plugins/PluginEntity.cs
similarity index 88%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Plugins/PluginEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Plugins/PluginEntity.cs
index 779b42fff..47e2ba74b 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Plugins/PluginEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Plugins/PluginEntity.cs
@@ -1,9 +1,9 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Plugins;
+namespace Artemis.Storage.Legacy.Entities.Plugins;
///
/// Represents the configuration of a plugin, each plugin has one configuration
///
-public class PluginEntity
+internal class PluginEntity
{
public PluginEntity()
{
@@ -19,7 +19,7 @@ public class PluginEntity
{
return new Artemis.Storage.Entities.Plugins.PluginEntity()
{
- Id = Id,
+ PluginGuid = Id,
IsEnabled = IsEnabled,
Features = Features.Select(f => f.Migrate()).ToList()
};
@@ -29,7 +29,7 @@ public class PluginEntity
///
/// Represents the configuration of a plugin feature, each feature has one configuration
///
-public class PluginFeatureEntity
+internal class PluginFeatureEntity
{
public string Type { get; set; } = string.Empty;
public bool IsEnabled { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Plugins/PluginSettingEntity.cs b/src/Artemis.Storage.Legacy/Entities/Plugins/PluginSettingEntity.cs
similarity index 85%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Plugins/PluginSettingEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Plugins/PluginSettingEntity.cs
index 2d10b80e2..587e7d1c8 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Plugins/PluginSettingEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Plugins/PluginSettingEntity.cs
@@ -1,9 +1,9 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Plugins;
+namespace Artemis.Storage.Legacy.Entities.Plugins;
///
/// Represents the setting of a plugin, a plugin can have multiple settings
///
-public class PluginSettingEntity
+internal class PluginSettingEntity
{
public Guid Id { get; set; }
public Guid PluginGuid { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Abstract/RenderElementEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Abstract/RenderElementEntity.cs
similarity index 58%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Abstract/RenderElementEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Abstract/RenderElementEntity.cs
index 98f01a41e..56b4e97fd 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Abstract/RenderElementEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Abstract/RenderElementEntity.cs
@@ -1,8 +1,8 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
+using Artemis.Storage.Legacy.Entities.Profile.Conditions;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Abstract;
+namespace Artemis.Storage.Legacy.Entities.Profile.Abstract;
-public abstract class RenderElementEntity
+internal abstract class RenderElementEntity
{
public Guid Id { get; set; }
public Guid ParentId { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/CategoryAdaptionHintEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/CategoryAdaptionHintEntity.cs
similarity index 52%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/CategoryAdaptionHintEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/CategoryAdaptionHintEntity.cs
index 3576c5cde..16ceb4d79 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/CategoryAdaptionHintEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/CategoryAdaptionHintEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
+namespace Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
-public class CategoryAdaptionHintEntity : IAdaptionHintEntity
+internal class CategoryAdaptionHintEntity : IAdaptionHintEntity
{
public int Category { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/DeviceAdaptionHintEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/DeviceAdaptionHintEntity.cs
similarity index 53%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/DeviceAdaptionHintEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/DeviceAdaptionHintEntity.cs
index f7a078867..dc4005707 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/DeviceAdaptionHintEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/DeviceAdaptionHintEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
+namespace Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
-public class DeviceAdaptionHintEntity : IAdaptionHintEntity
+internal class DeviceAdaptionHintEntity : IAdaptionHintEntity
{
public int DeviceType { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/IAdaptionHintEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/IAdaptionHintEntity.cs
similarity index 82%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/IAdaptionHintEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/IAdaptionHintEntity.cs
index 9ff03f4bd..a18f3b6ac 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/IAdaptionHintEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/IAdaptionHintEntity.cs
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
+namespace Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
[JsonDerivedType(typeof(CategoryAdaptionHintEntity), "Category")]
[JsonDerivedType(typeof(DeviceAdaptionHintEntity), "Device")]
diff --git a/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/KeyboardSectionAdaptionHintEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/KeyboardSectionAdaptionHintEntity.cs
new file mode 100644
index 000000000..4d67359c6
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/KeyboardSectionAdaptionHintEntity.cs
@@ -0,0 +1,6 @@
+namespace Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
+
+internal class KeyboardSectionAdaptionHintEntity : IAdaptionHintEntity
+{
+ public int Section { get; set; }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/SingleLedAdaptionHintEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/SingleLedAdaptionHintEntity.cs
similarity index 52%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/SingleLedAdaptionHintEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/SingleLedAdaptionHintEntity.cs
index 98d192595..9d03535d3 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/SingleLedAdaptionHintEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/AdaptionHints/SingleLedAdaptionHintEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
+namespace Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
-public class SingleLedAdaptionHintEntity : IAdaptionHintEntity
+internal class SingleLedAdaptionHintEntity : IAdaptionHintEntity
{
public int LedId { get; set; }
diff --git a/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/AlwaysOnConditionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/AlwaysOnConditionEntity.cs
new file mode 100644
index 000000000..498d97885
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/AlwaysOnConditionEntity.cs
@@ -0,0 +1,3 @@
+namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
+
+internal class AlwaysOnConditionEntity : IConditionEntity;
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/EventConditionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/EventConditionEntity.cs
similarity index 55%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/EventConditionEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Conditions/EventConditionEntity.cs
index 2fea241b0..574d5d42e 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/EventConditionEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/EventConditionEntity.cs
@@ -1,8 +1,8 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+using Artemis.Storage.Legacy.Entities.Profile.Nodes;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
+namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
-public class EventConditionEntity : IConditionEntity
+internal class EventConditionEntity : IConditionEntity
{
public int TriggerMode { get; set; }
public int OverlapMode { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/IConditionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/IConditionEntity.cs
similarity index 81%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/IConditionEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Conditions/IConditionEntity.cs
index bc78042aa..ab5086aa9 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/IConditionEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/IConditionEntity.cs
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
+namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
[JsonDerivedType(typeof(AlwaysOnConditionEntity), "AlwaysOn")]
[JsonDerivedType(typeof(EventConditionEntity), "Event")]
diff --git a/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/PlayOnceConditionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/PlayOnceConditionEntity.cs
new file mode 100644
index 000000000..798ef08c2
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/PlayOnceConditionEntity.cs
@@ -0,0 +1,3 @@
+namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
+
+internal class PlayOnceConditionEntity : IConditionEntity;
\ No newline at end of file
diff --git a/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/StaticConditionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/StaticConditionEntity.cs
new file mode 100644
index 000000000..a4bfcc06b
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Conditions/StaticConditionEntity.cs
@@ -0,0 +1,10 @@
+using Artemis.Storage.Legacy.Entities.Profile.Nodes;
+
+namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
+
+internal class StaticConditionEntity : IConditionEntity
+{
+ public int PlayMode { get; set; }
+ public int StopMode { get; set; }
+ public NodeScriptEntity? Script { get; set; }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Legacy/Entities/Profile/DataBindings/DataBindingEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/DataBindings/DataBindingEntity.cs
new file mode 100644
index 000000000..39be84d72
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/DataBindings/DataBindingEntity.cs
@@ -0,0 +1,9 @@
+using Artemis.Storage.Legacy.Entities.Profile.Nodes;
+
+namespace Artemis.Storage.Legacy.Entities.Profile.DataBindings;
+
+internal class DataBindingEntity
+{
+ public bool IsEnabled { get; set; }
+ public NodeScriptEntity? NodeScript { get; set; }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/DataModelPathEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/DataModelPathEntity.cs
similarity index 59%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/DataModelPathEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/DataModelPathEntity.cs
index 0783e603f..4ebef8bc4 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/DataModelPathEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/DataModelPathEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class DataModelPathEntity
+internal class DataModelPathEntity
{
public string Path { get; set; } = string.Empty;
public string? DataModelId { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/FolderEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/FolderEntity.cs
similarity index 63%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/FolderEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/FolderEntity.cs
index ef181ff5d..ae467caa7 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/FolderEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/FolderEntity.cs
@@ -1,9 +1,9 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Abstract;
+using Artemis.Storage.Legacy.Entities.Profile.Abstract;
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class FolderEntity : RenderElementEntity
+internal class FolderEntity : RenderElementEntity
{
public int Order { get; set; }
public string? Name { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/KeyframeEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/KeyframeEntity.cs
similarity index 66%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/KeyframeEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/KeyframeEntity.cs
index fae285769..6f75fe047 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/KeyframeEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/KeyframeEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class KeyframeEntity
+internal class KeyframeEntity
{
public TimeSpan Position { get; set; }
public int Timeline { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerBrushEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/LayerBrushEntity.cs
similarity index 66%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerBrushEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/LayerBrushEntity.cs
index f0579e9ac..254c19e71 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerBrushEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/LayerBrushEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class LayerBrushEntity
+internal class LayerBrushEntity
{
public string ProviderId { get; set; } = string.Empty;
public string BrushType { get; set; } = string.Empty;
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerEffectEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/LayerEffectEntity.cs
similarity index 77%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerEffectEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/LayerEffectEntity.cs
index b3b8e5bdb..7f4c7e696 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerEffectEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/LayerEffectEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class LayerEffectEntity
+internal class LayerEffectEntity
{
public string ProviderId { get; set; } = string.Empty;
public string EffectType { get; set; } = string.Empty;
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/LayerEntity.cs
similarity index 73%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/LayerEntity.cs
index 57d5ea555..d00a62c20 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LayerEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/LayerEntity.cs
@@ -1,10 +1,10 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Abstract;
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
+using Artemis.Storage.Legacy.Entities.Profile.Abstract;
+using Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class LayerEntity : RenderElementEntity
+internal class LayerEntity : RenderElementEntity
{
public LayerEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LedEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/LedEntity.cs
similarity index 92%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LedEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/LedEntity.cs
index b456a138c..5f7328bd6 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/LedEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/LedEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class LedEntity
+internal class LedEntity
{
public string LedName { get; set; } = string.Empty;
public string DeviceIdentifier { get; set; } = string.Empty;
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeConnectionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeConnectionEntity.cs
similarity index 90%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeConnectionEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeConnectionEntity.cs
index d256cce6b..c186db470 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeConnectionEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeConnectionEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+namespace Artemis.Storage.Legacy.Entities.Profile.Nodes;
-public class NodeConnectionEntity
+internal class NodeConnectionEntity
{
public NodeConnectionEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeEntity.cs
similarity index 92%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeEntity.cs
index b25e9b0f7..314964430 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+namespace Artemis.Storage.Legacy.Entities.Profile.Nodes;
-public class NodeEntity
+internal class NodeEntity
{
public NodeEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodePinCollectionEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodePinCollectionEntity.cs
similarity index 79%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodePinCollectionEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodePinCollectionEntity.cs
index cdec98e6a..b10944b48 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodePinCollectionEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodePinCollectionEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+namespace Artemis.Storage.Legacy.Entities.Profile.Nodes;
-public class NodePinCollectionEntity
+internal class NodePinCollectionEntity
{
public NodePinCollectionEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeScriptEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeScriptEntity.cs
similarity index 78%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeScriptEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeScriptEntity.cs
index 5afeb39df..8da434571 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Nodes/NodeScriptEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/Nodes/NodeScriptEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+namespace Artemis.Storage.Legacy.Entities.Profile.Nodes;
-public class NodeScriptEntity
+internal class NodeScriptEntity
{
public NodeScriptEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileCategoryEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileCategoryEntity.cs
similarity index 96%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileCategoryEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/ProfileCategoryEntity.cs
index 0323db70d..c5b61012b 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileCategoryEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileCategoryEntity.cs
@@ -3,9 +3,9 @@ using Artemis.Storage.Entities.Profile;
using LiteDB;
using Serilog;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class ProfileCategoryEntity
+internal class ProfileCategoryEntity
{
public Guid Id { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileConfigurationEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileConfigurationEntity.cs
similarity index 83%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileConfigurationEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/ProfileConfigurationEntity.cs
index 89f68fe1d..482672a60 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileConfigurationEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileConfigurationEntity.cs
@@ -1,8 +1,8 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+using Artemis.Storage.Legacy.Entities.Profile.Nodes;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class ProfileConfigurationEntity
+internal class ProfileConfigurationEntity
{
public string Name { get; set; } = string.Empty;
public string? MaterialIcon { get; set; }
diff --git a/src/Artemis.Storage.Legacy/Entities/Profile/ProfileConfigurationHotkeyEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileConfigurationHotkeyEntity.cs
new file mode 100644
index 000000000..30cfb4a06
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileConfigurationHotkeyEntity.cs
@@ -0,0 +1,7 @@
+namespace Artemis.Storage.Legacy.Entities.Profile;
+
+internal class ProfileConfigurationHotkeyEntity
+{
+ public int? Key { get; set; }
+ public int? Modifiers { get; set; }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileEntity.cs
similarity index 84%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/ProfileEntity.cs
index cbfde4b61..dbbbfee9d 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/ProfileEntity.cs
@@ -1,8 +1,8 @@
-using Artemis.Storage.Migrator.Legacy.Entities.General;
+using Artemis.Storage.Legacy.Entities.General;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class ProfileEntity
+internal class ProfileEntity
{
public ProfileEntity()
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/PropertyEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/PropertyEntity.cs
similarity index 64%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/PropertyEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/PropertyEntity.cs
index 1a0a5d4b6..44a4406ab 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/PropertyEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/PropertyEntity.cs
@@ -1,8 +1,8 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.DataBindings;
+using Artemis.Storage.Legacy.Entities.Profile.DataBindings;
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class PropertyEntity
+internal class PropertyEntity
{
public string Identifier { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/PropertyGroupEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/PropertyGroupEntity.cs
similarity index 68%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/PropertyGroupEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/PropertyGroupEntity.cs
index 8097d36ba..2c7f316bb 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/PropertyGroupEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/PropertyGroupEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class PropertyGroupEntity
+internal class PropertyGroupEntity
{
public string Identifier { get; set; } = string.Empty;
public List Properties { get; set; } = new();
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/TimelineEntity.cs b/src/Artemis.Storage.Legacy/Entities/Profile/TimelineEntity.cs
similarity index 63%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Profile/TimelineEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Profile/TimelineEntity.cs
index a9401abac..9a1f400e4 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/TimelineEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Profile/TimelineEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
+namespace Artemis.Storage.Legacy.Entities.Profile;
-public class TimelineEntity
+internal class TimelineEntity
{
public TimeSpan StartSegmentLength { get; set; }
public TimeSpan MainSegmentLength { get; set; }
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Surface/DeviceEntity.cs b/src/Artemis.Storage.Legacy/Entities/Surface/DeviceEntity.cs
similarity index 93%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Surface/DeviceEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Surface/DeviceEntity.cs
index 52d86fbcc..fc3988dba 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Surface/DeviceEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Surface/DeviceEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Surface;
+namespace Artemis.Storage.Legacy.Entities.Surface;
-public class DeviceEntity
+internal class DeviceEntity
{
public DeviceEntity()
{
@@ -65,13 +65,13 @@ public class DeviceEntity
}
}
-public class InputMappingEntity
+internal class InputMappingEntity
{
public int OriginalLedId { get; set; }
public int MappedLedId { get; set; }
}
-public class DeviceInputIdentifierEntity
+internal class DeviceInputIdentifierEntity
{
public string InputProvider { get; set; } = string.Empty;
public object Identifier { get; set; } = string.Empty;
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Workshop/EntryEntity.cs b/src/Artemis.Storage.Legacy/Entities/Workshop/EntryEntity.cs
similarity index 91%
rename from src/Artemis.Storage.Migrator/Legacy/Entities/Workshop/EntryEntity.cs
rename to src/Artemis.Storage.Legacy/Entities/Workshop/EntryEntity.cs
index c5fea30d2..ec0d6c091 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Workshop/EntryEntity.cs
+++ b/src/Artemis.Storage.Legacy/Entities/Workshop/EntryEntity.cs
@@ -1,6 +1,6 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Workshop;
+namespace Artemis.Storage.Legacy.Entities.Workshop;
-public class EntryEntity
+internal class EntryEntity
{
public Guid Id { get; set; }
diff --git a/src/Artemis.Storage.Legacy/LegacyMigrationService.cs b/src/Artemis.Storage.Legacy/LegacyMigrationService.cs
new file mode 100644
index 000000000..1c3b35d4f
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/LegacyMigrationService.cs
@@ -0,0 +1,163 @@
+using Artemis.Core;
+using Artemis.Storage.Legacy.Entities.General;
+using Artemis.Storage.Legacy.Entities.Plugins;
+using Artemis.Storage.Legacy.Entities.Profile;
+using Artemis.Storage.Legacy.Entities.Surface;
+using Artemis.Storage.Legacy.Entities.Workshop;
+using Artemis.Storage.Legacy.Migrations;
+using Artemis.Storage.Legacy.Migrations.Storage;
+using DryIoc;
+using LiteDB;
+using Serilog;
+
+namespace Artemis.Storage.Legacy;
+
+public static class LegacyMigrationService
+{
+ public static void MigrateToSqlite(IContainer container)
+ {
+ ILogger logger = container.Resolve();
+
+ // Before creating a DB context which is kinda expensive, check if there's anything to migrate
+ if (!File.Exists(Path.Combine(Constants.DataFolder, "database.db")))
+ {
+ logger.Information("No legacy database found, nothing to migrate");
+ return;
+ }
+
+ using ArtemisDbContext dbContext = container.Resolve();
+ MigrateToSqlite(logger, dbContext);
+ }
+
+ public static void MigrateToSqlite(ILogger logger, ArtemisDbContext dbContext)
+ {
+ if (!File.Exists(Path.Combine(Constants.DataFolder, "database.db")))
+ {
+ logger.Information("No legacy database found, nothing to migrate");
+ return;
+ }
+
+ logger.Information("Migrating legacy database...");
+
+ try
+ {
+ // Copy the database before using it, we're going to make some modifications to it and we don't want to mess up the original
+ string databasePath = Path.Combine(Constants.DataFolder, "database.db");
+ string tempPath = Path.Combine(Constants.DataFolder, "temp.db");
+ File.Copy(databasePath, tempPath, true);
+
+ using LiteRepository repository = new($"FileName={tempPath}");
+
+ // Apply pending LiteDB migrations, this includes a migration that transforms namespaces to Artemis.Storage.Legacy
+ ApplyPendingMigrations(logger, repository);
+
+ // Devices
+ if (!dbContext.Devices.Any())
+ {
+ logger.Information("Migrating devices");
+ List legacyDevices = repository.Query().Include(s => s.InputIdentifiers).ToList();
+ dbContext.Devices.AddRange(legacyDevices.Select(l => l.Migrate()));
+ dbContext.SaveChanges();
+ }
+
+ // Entries
+ if (!dbContext.Entries.Any())
+ {
+ logger.Information("Migrating entries");
+ List legacyEntries = repository.Query().ToList();
+ dbContext.Entries.AddRange(legacyEntries.Select(l => l.Migrate()));
+ dbContext.SaveChanges();
+ }
+
+ // Plugins
+ if (!dbContext.Plugins.Any())
+ {
+ logger.Information("Migrating plugins");
+ List legacyPlugins = repository.Query().ToList();
+ dbContext.Plugins.AddRange(legacyPlugins.Select(l => l.Migrate()));
+ dbContext.SaveChanges();
+ }
+
+ // PluginSettings
+ if (!dbContext.PluginSettings.Any())
+ {
+ logger.Information("Migrating plugin settings");
+ List legacyPluginSettings = repository.Query().ToList();
+ dbContext.PluginSettings.AddRange(legacyPluginSettings.Select(l => l.Migrate()));
+ dbContext.SaveChanges();
+ }
+
+ // ProfileCategories
+ if (!dbContext.ProfileCategories.Any())
+ {
+ logger.Information("Migrating profile categories");
+ List legacyProfileCategories = repository.Query().ToList();
+ ILiteStorage profileIcons = repository.Database.GetStorage("profileIcons");
+ List legacyProfiles = repository.Query().ToList();
+ dbContext.ProfileCategories.AddRange(legacyProfileCategories.Select(l => l.Migrate(logger, legacyProfiles, profileIcons)));
+ dbContext.SaveChanges();
+ }
+
+ // Releases
+ if (!dbContext.Releases.Any())
+ {
+ logger.Information("Migrating releases");
+ List legacyReleases = repository.Query().ToList();
+ dbContext.Releases.AddRange(legacyReleases.Select(l => l.Migrate()));
+ dbContext.SaveChanges();
+ }
+
+ // After a successful migration, keep the legacy database around for a while
+ File.Move(Path.Combine(Constants.DataFolder, "database.db"), Path.Combine(Constants.DataFolder, "legacy.db"));
+
+ logger.Information("Legacy database migrated");
+ }
+ catch (Exception e)
+ {
+ logger.Error(e, "Failed to migrate legacy database");
+ throw;
+ }
+ finally
+ {
+ File.Delete(Path.Combine(Constants.DataFolder, "temp.db"));
+ }
+ }
+
+ private static void ApplyPendingMigrations(ILogger logger, LiteRepository repository)
+ {
+ List migrations =
+ [
+ new M0020AvaloniaReset(),
+ new M0021GradientNodes(),
+ new M0022TransitionNodes(),
+ new M0023LayoutProviders(),
+ new M0024NodeProviders(),
+ new M0025NodeProvidersProfileConfig(),
+ new M0026NodeStorage(logger),
+ new M0027Namespace()
+ ];
+
+ foreach (IStorageMigration storageMigration in migrations.OrderBy(m => m.UserVersion))
+ {
+ if (repository.Database.UserVersion >= storageMigration.UserVersion)
+ continue;
+
+ logger.Information("Applying storage migration {storageMigration} to update DB from v{oldVersion} to v{newVersion}",
+ storageMigration.GetType().Name, repository.Database.UserVersion, storageMigration.UserVersion);
+
+ repository.Database.BeginTrans();
+ try
+ {
+ storageMigration.Apply(repository);
+ }
+ catch (Exception)
+ {
+ repository.Database.Rollback();
+ throw;
+ }
+
+ repository.Database.Commit();
+ repository.Database.UserVersion = storageMigration.UserVersion;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/IProfileMigration.cs b/src/Artemis.Storage.Legacy/Migrations/IProfileMigration.cs
similarity index 75%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/IProfileMigration.cs
rename to src/Artemis.Storage.Legacy/Migrations/IProfileMigration.cs
index f5e9d8092..53d1d1eda 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/IProfileMigration.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/IProfileMigration.cs
@@ -1,6 +1,6 @@
using System.Text.Json.Nodes;
-namespace Artemis.Storage.Migrator.Legacy.Migrations;
+namespace Artemis.Storage.Legacy.Migrations;
public interface IProfileMigration
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/IStorageMigration.cs b/src/Artemis.Storage.Legacy/Migrations/IStorageMigration.cs
similarity index 70%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/IStorageMigration.cs
rename to src/Artemis.Storage.Legacy/Migrations/IStorageMigration.cs
index 4aee9aabd..18ba559ca 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/IStorageMigration.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/IStorageMigration.cs
@@ -1,6 +1,6 @@
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations;
+namespace Artemis.Storage.Legacy.Migrations;
public interface IStorageMigration
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0020AvaloniaReset.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0020AvaloniaReset.cs
similarity index 76%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0020AvaloniaReset.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0020AvaloniaReset.cs
index de3478e7b..685585ffb 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0020AvaloniaReset.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0020AvaloniaReset.cs
@@ -1,8 +1,8 @@
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0020AvaloniaReset : IStorageMigration
+internal class M0020AvaloniaReset : IStorageMigration
{
public int UserVersion => 20;
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0021GradientNodes.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0021GradientNodes.cs
similarity index 92%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0021GradientNodes.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0021GradientNodes.cs
index 354525008..02998e98c 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0021GradientNodes.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0021GradientNodes.cs
@@ -1,10 +1,10 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile;
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+using Artemis.Storage.Legacy.Entities.Profile;
+using Artemis.Storage.Legacy.Entities.Profile.Nodes;
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0021GradientNodes : IStorageMigration
+internal class M0021GradientNodes : IStorageMigration
{
private void MigrateDataBinding(PropertyEntity property)
{
@@ -59,7 +59,7 @@ public class M0021GradientNodes : IStorageMigration
{
if (propertyGroup == null)
return;
-
+
foreach (PropertyGroupEntity propertyGroupPropertyGroup in propertyGroup.PropertyGroups)
MigrateDataBinding(propertyGroupPropertyGroup);
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0022TransitionNodes.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0022TransitionNodes.cs
similarity index 91%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0022TransitionNodes.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0022TransitionNodes.cs
index 7556b7840..369ab130c 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0022TransitionNodes.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0022TransitionNodes.cs
@@ -1,11 +1,11 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile;
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
+using Artemis.Storage.Legacy.Entities.Profile;
+using Artemis.Storage.Legacy.Entities.Profile.Conditions;
+using Artemis.Storage.Legacy.Entities.Profile.Nodes;
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0022TransitionNodes : IStorageMigration
+internal class M0022TransitionNodes : IStorageMigration
{
private void MigrateNodeScript(NodeScriptEntity? nodeScript)
{
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0023LayoutProviders.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0023LayoutProviders.cs
similarity index 88%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0023LayoutProviders.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0023LayoutProviders.cs
index 602ba6f2e..1a8d7500b 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0023LayoutProviders.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0023LayoutProviders.cs
@@ -1,8 +1,8 @@
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0023LayoutProviders : IStorageMigration
+internal class M0023LayoutProviders : IStorageMigration
{
public int UserVersion => 23;
@@ -19,9 +19,13 @@ public class M0023LayoutProviders : IStorageMigration
bsonDocument.Add("LayoutParameter", new BsonValue(customLayoutPath.AsString));
}
else if (bsonDocument.TryGetValue("DisableDefaultLayout", out BsonValue disableDefaultLayout) && disableDefaultLayout.AsBoolean)
+ {
bsonDocument.Add("LayoutType", new BsonValue("None"));
+ }
else
+ {
bsonDocument.Add("LayoutType", new BsonValue("Default"));
+ }
bsonDocument.Remove("CustomLayoutPath");
bsonDocument.Remove("DisableDefaultLayout");
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0024NodeProviders.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0024NodeProviders.cs
similarity index 93%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0024NodeProviders.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0024NodeProviders.cs
index 37d61c5d5..4617ae6d1 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0024NodeProviders.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0024NodeProviders.cs
@@ -1,8 +1,8 @@
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0024NodeProviders : IStorageMigration
+internal class M0024NodeProviders : IStorageMigration
{
public int UserVersion => 24;
@@ -20,6 +20,7 @@ public class M0024NodeProviders : IStorageMigration
categoriesToUpdate.Add(profileCategoryBson);
}
}
+
categoryCollection.Update(categoriesToUpdate);
ILiteCollection collection = repository.Database.GetCollection("ProfileEntity");
@@ -28,15 +29,12 @@ public class M0024NodeProviders : IStorageMigration
{
BsonArray? folders = profileBson["Folders"]?.AsArray;
BsonArray? layers = profileBson["Layers"]?.AsArray;
-
+
if (folders != null)
- {
foreach (BsonValue folder in folders)
MigrateProfileElement(folder.AsDocument);
- }
-
+
if (layers != null)
- {
foreach (BsonValue layer in layers)
{
MigrateProfileElement(layer.AsDocument);
@@ -44,8 +42,7 @@ public class M0024NodeProviders : IStorageMigration
MigratePropertyGroup(layer.AsDocument["TransformPropertyGroup"].AsDocument);
MigratePropertyGroup(layer.AsDocument["LayerBrush"]?["PropertyGroup"].AsDocument);
}
- }
-
+
profilesToUpdate.Add(profileBson);
}
@@ -56,10 +53,8 @@ public class M0024NodeProviders : IStorageMigration
{
BsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray;
if (layerEffects != null)
- {
foreach (BsonValue layerEffect in layerEffects)
MigratePropertyGroup(layerEffect.AsDocument["PropertyGroup"].AsDocument);
- }
BsonValue? displayCondition = profileElement["DisplayCondition"];
if (displayCondition != null)
@@ -75,16 +70,12 @@ public class M0024NodeProviders : IStorageMigration
BsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray;
if (properties != null)
- {
foreach (BsonValue property in properties)
MigrateNodeScript(property.AsDocument["DataBinding"]?["NodeScript"]?.AsDocument);
- }
if (propertyGroups != null)
- {
foreach (BsonValue childPropertyGroup in propertyGroups)
MigratePropertyGroup(childPropertyGroup.AsDocument);
- }
}
private void MigrateNodeScript(BsonDocument? nodeScript)
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0025NodeProvidersProfileConfig.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0025NodeProvidersProfileConfig.cs
similarity index 91%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0025NodeProvidersProfileConfig.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0025NodeProvidersProfileConfig.cs
index bbb121956..bff6ff6ff 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0025NodeProvidersProfileConfig.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0025NodeProvidersProfileConfig.cs
@@ -1,8 +1,8 @@
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0025NodeProvidersProfileConfig : IStorageMigration
+internal class M0025NodeProvidersProfileConfig : IStorageMigration
{
public int UserVersion => 25;
@@ -20,13 +20,14 @@ public class M0025NodeProvidersProfileConfig : IStorageMigration
profile["Version"] = 2;
MigrateNodeScript(profile["ActivationCondition"]?.AsDocument);
}
+
toUpdate.Add(profileCategoryBson);
}
}
-
+
categoryCollection.Update(toUpdate);
}
-
+
private void MigrateNodeScript(BsonDocument? nodeScript)
{
if (nodeScript == null || nodeScript.Keys.Count == 0)
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0026NodeStorage.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0026NodeStorage.cs
similarity index 97%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0026NodeStorage.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0026NodeStorage.cs
index 1212455bb..cbea0db8d 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0026NodeStorage.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0026NodeStorage.cs
@@ -3,9 +3,9 @@ using System.Text.Json.Nodes;
using LiteDB;
using Serilog;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0026NodeStorage : IStorageMigration
+internal class M0026NodeStorage : IStorageMigration
{
private readonly ILogger _logger;
@@ -45,13 +45,10 @@ public class M0026NodeStorage : IStorageMigration
BsonArray? layers = profileBson["Layers"]?.AsArray;
if (folders != null)
- {
foreach (BsonValue folder in folders)
MigrateProfileElement(folder.AsDocument);
- }
if (layers != null)
- {
foreach (BsonValue layer in layers)
{
MigrateProfileElement(layer.AsDocument);
@@ -59,7 +56,6 @@ public class M0026NodeStorage : IStorageMigration
MigratePropertyGroup(layer.AsDocument["TransformPropertyGroup"].AsDocument);
MigratePropertyGroup(layer.AsDocument["LayerBrush"]?["PropertyGroup"].AsDocument);
}
- }
profilesToUpdate.Add(profileBson);
}
@@ -71,10 +67,8 @@ public class M0026NodeStorage : IStorageMigration
{
BsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray;
if (layerEffects != null)
- {
foreach (BsonValue layerEffect in layerEffects)
MigratePropertyGroup(layerEffect.AsDocument["PropertyGroup"].AsDocument);
- }
BsonValue? displayCondition = profileElement["DisplayCondition"];
if (displayCondition != null)
@@ -90,16 +84,12 @@ public class M0026NodeStorage : IStorageMigration
BsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray;
if (properties != null)
- {
foreach (BsonValue property in properties)
MigrateNodeScript(property.AsDocument["DataBinding"]?["NodeScript"]?.AsDocument);
- }
if (propertyGroups != null)
- {
foreach (BsonValue childPropertyGroup in propertyGroups)
MigratePropertyGroup(childPropertyGroup.AsDocument);
- }
}
private void MigrateNodeScript(BsonDocument? nodeScript)
@@ -112,10 +102,8 @@ public class M0026NodeStorage : IStorageMigration
return;
foreach (BsonValue node in nodes)
- {
// Migrate the storage of the node
node["Storage"] = MigrateNodeStorageJson(node.AsDocument["Storage"]?.AsString, _logger);
- }
}
private static string? MigrateNodeStorageJson(string? json, ILogger logger)
diff --git a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0027Namespace.cs b/src/Artemis.Storage.Legacy/Migrations/Storage/M0027Namespace.cs
similarity index 79%
rename from src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0027Namespace.cs
rename to src/Artemis.Storage.Legacy/Migrations/Storage/M0027Namespace.cs
index 6a98a25eb..b0bee99a1 100644
--- a/src/Artemis.Storage.Migrator/Legacy/Migrations/Storage/M0027Namespace.cs
+++ b/src/Artemis.Storage.Legacy/Migrations/Storage/M0027Namespace.cs
@@ -1,8 +1,8 @@
using LiteDB;
-namespace Artemis.Storage.Migrator.Legacy.Migrations.Storage;
+namespace Artemis.Storage.Legacy.Migrations.Storage;
-public class M0027Namespace : IStorageMigration
+internal class M0027Namespace : IStorageMigration
{
public int UserVersion => 27;
@@ -25,21 +25,17 @@ public class M0027Namespace : IStorageMigration
foreach ((string? key, BsonValue? value) in document)
{
if (key == "_type")
- {
document[key] = document[key].AsString
- .Replace("Artemis.Storage.Entities.Profile", "Artemis.Storage.Migrator.Legacy.Entities.Profile")
- .Replace(", Artemis.Storage", ", Artemis.Storage.Migrator");
- }
+ .Replace("Artemis.Storage.Entities", "Artemis.Storage.Legacy.Entities")
+ .Replace(", Artemis.Storage", ", Artemis.Storage.Legacy");
else if (value.IsDocument)
MigrateDocument(value.AsDocument);
else if (value.IsArray)
- {
foreach (BsonValue bsonValue in value.AsArray)
{
if (bsonValue.IsDocument)
MigrateDocument(bsonValue.AsDocument);
}
- }
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Legacy/Program.cs b/src/Artemis.Storage.Legacy/Program.cs
new file mode 100644
index 000000000..c225e03f5
--- /dev/null
+++ b/src/Artemis.Storage.Legacy/Program.cs
@@ -0,0 +1,22 @@
+// using Artemis.Core.DryIoc;
+// using Artemis.Storage;
+// using Artemis.Storage.Legacy;
+// using DryIoc;
+// using Microsoft.EntityFrameworkCore;
+// using Serilog;
+//
+// using Container container = new(rules => rules
+// .WithMicrosoftDependencyInjectionRules()
+// .WithConcreteTypeDynamicRegistrations()
+// .WithoutThrowOnRegisteringDisposableTransient());
+//
+// container.RegisterCore();
+//
+// ILogger logger = container.Resolve();
+// ArtemisDbContext dbContext = container.Resolve();
+//
+// logger.Information("Applying pending migrations...");
+// dbContext.Database.Migrate();
+// logger.Information("Pending migrations applied");
+//
+// MigrationService.MigrateToSqlite(logger, dbContext);
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/KeyboardSectionAdaptionHintEntity.cs b/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/KeyboardSectionAdaptionHintEntity.cs
deleted file mode 100644
index 075f3ad9a..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/AdaptionHints/KeyboardSectionAdaptionHintEntity.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
-
-public class KeyboardSectionAdaptionHintEntity : IAdaptionHintEntity
-{
- public int Section { get; set; }
-}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/AlwaysOnConditionEntity.cs b/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/AlwaysOnConditionEntity.cs
deleted file mode 100644
index e644c4331..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/AlwaysOnConditionEntity.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
-
-public class AlwaysOnConditionEntity : IConditionEntity;
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/PlayOnceConditionEntity.cs b/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/PlayOnceConditionEntity.cs
deleted file mode 100644
index 82fb095b1..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/PlayOnceConditionEntity.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
-
-public class PlayOnceConditionEntity : IConditionEntity;
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/StaticConditionEntity.cs b/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/StaticConditionEntity.cs
deleted file mode 100644
index 065bd92bd..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/Conditions/StaticConditionEntity.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
-
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
-
-public class StaticConditionEntity : IConditionEntity
-{
- public int PlayMode { get; set; }
- public int StopMode { get; set; }
- public NodeScriptEntity? Script { get; set; }
-}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/DataBindings/DataBindingEntity.cs b/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/DataBindings/DataBindingEntity.cs
deleted file mode 100644
index 74aa3851e..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/DataBindings/DataBindingEntity.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Artemis.Storage.Migrator.Legacy.Entities.Profile.Nodes;
-
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.DataBindings;
-
-public class DataBindingEntity
-{
- public bool IsEnabled { get; set; }
- public NodeScriptEntity? NodeScript { get; set; }
-}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileConfigurationHotkeyEntity.cs b/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileConfigurationHotkeyEntity.cs
deleted file mode 100644
index a0572cc91..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/Entities/Profile/ProfileConfigurationHotkeyEntity.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
-
-public class ProfileConfigurationHotkeyEntity
-{
- public int? Key { get; set; }
- public int? Modifiers { get; set; }
-}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Legacy/StorageMigrationService.cs b/src/Artemis.Storage.Migrator/Legacy/StorageMigrationService.cs
deleted file mode 100644
index 86f4f1384..000000000
--- a/src/Artemis.Storage.Migrator/Legacy/StorageMigrationService.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Artemis.Storage.Migrator.Legacy.Migrations;
-using LiteDB;
-using Serilog;
-
-namespace Artemis.Storage.Migrator.Legacy;
-
-public static class StorageMigrationService
-{
- public static void ApplyPendingMigrations(ILogger logger, LiteRepository repository, IList migrations)
- {
- foreach (IStorageMigration storageMigration in migrations.OrderBy(m => m.UserVersion))
- {
- if (repository.Database.UserVersion >= storageMigration.UserVersion)
- continue;
-
- logger.Information("Applying storage migration {storageMigration} to update DB from v{oldVersion} to v{newVersion}",
- storageMigration.GetType().Name, repository.Database.UserVersion, storageMigration.UserVersion);
-
- repository.Database.BeginTrans();
- try
- {
- storageMigration.Apply(repository);
- }
- catch (Exception)
- {
- repository.Database.Rollback();
- throw;
- }
-
- repository.Database.Commit();
- repository.Database.UserVersion = storageMigration.UserVersion;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/Program.cs b/src/Artemis.Storage.Migrator/Program.cs
deleted file mode 100644
index ba15b7bfa..000000000
--- a/src/Artemis.Storage.Migrator/Program.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-using Artemis.Core;
-using Artemis.Core.DryIoc;
-using Artemis.Storage.Migrator.Legacy;
-using Artemis.Storage.Migrator.Legacy.Entities.General;
-using Artemis.Storage.Migrator.Legacy.Entities.Plugins;
-using Artemis.Storage.Migrator.Legacy.Entities.Profile;
-using Artemis.Storage.Migrator.Legacy.Entities.Surface;
-using Artemis.Storage.Migrator.Legacy.Entities.Workshop;
-using Artemis.Storage.Migrator.Legacy.Migrations.Storage;
-using DryIoc;
-using LiteDB;
-using Microsoft.EntityFrameworkCore;
-using Serilog;
-
-namespace Artemis.Storage.Migrator;
-
-class Program
-{
- static void Main(string[] args)
- {
- using Container container = new(rules => rules
- .WithMicrosoftDependencyInjectionRules()
- .WithConcreteTypeDynamicRegistrations()
- .WithoutThrowOnRegisteringDisposableTransient());
-
- container.RegisterCore();
-
- ILogger logger = container.Resolve();
- ArtemisDbContext dbContext = container.Resolve();
- logger.Information("Applying pending migrations...");
- dbContext.Database.Migrate();
- logger.Information("Pending migrations applied");
-
- if (!File.Exists(Path.Combine(Constants.DataFolder, "database.db")))
- {
- logger.Information("No legacy database found, nothing to migrate");
- return;
- }
-
- logger.Information("Migrating legacy database...");
-
- try
- {
- MigrateLegacyDatabase(logger, dbContext);
- // After a successful migration, keep the legacy database around for a while
- File.Move(Path.Combine(Constants.DataFolder, "database.db"), Path.Combine(Constants.DataFolder, "legacy.db"));
- }
- catch (Exception e)
- {
- logger.Error(e, "Failed to migrate legacy database");
- throw;
- }
- finally
- {
- File.Delete(Path.Combine(Constants.DataFolder, "temp.db"));
- }
-
- logger.Information("Legacy database migrated");
- }
-
- private static void MigrateLegacyDatabase(ILogger logger, ArtemisDbContext dbContext)
- {
- // Copy the database before using it, we're going to make some modifications to it and we don't want to mess up the original
- string databasePath = Path.Combine(Constants.DataFolder, "database.db");
- string tempPath = Path.Combine(Constants.DataFolder, "temp.db");
- File.Copy(databasePath, tempPath, true);
-
- using LiteRepository repository = new($"FileName={tempPath}");
-
- // Apply pending LiteDB migrations, this includes a migration that transforms namespaces to Artemis.Storage.Migrator
- StorageMigrationService.ApplyPendingMigrations(
- logger,
- repository,
- [
- new M0020AvaloniaReset(),
- new M0021GradientNodes(),
- new M0022TransitionNodes(),
- new M0023LayoutProviders(),
- new M0024NodeProviders(),
- new M0025NodeProvidersProfileConfig(),
- new M0026NodeStorage(logger),
- new M0027Namespace(),
- ]
- );
-
- // Devices
- if (!dbContext.Devices.Any())
- {
- logger.Information("Migrating devices");
- List legacyDevices = repository.Query().Include(s => s.InputIdentifiers).ToList();
- dbContext.Devices.AddRange(legacyDevices.Select(l => l.Migrate()));
- dbContext.SaveChanges();
- }
-
- // Entries
- if (!dbContext.Entries.Any())
- {
- logger.Information("Migrating entries");
- List legacyEntries = repository.Query().ToList();
- dbContext.Entries.AddRange(legacyEntries.Select(l => l.Migrate()));
- dbContext.SaveChanges();
- }
-
- // Plugins
- if (!dbContext.Plugins.Any())
- {
- logger.Information("Migrating plugins");
- List legacyPlugins = repository.Query().ToList();
- dbContext.Plugins.AddRange(legacyPlugins.Select(l => l.Migrate()));
- dbContext.SaveChanges();
- }
-
- // PluginSettings
- if (!dbContext.PluginSettings.Any())
- {
- logger.Information("Migrating plugin settings");
- List legacyPluginSettings = repository.Query().ToList();
- dbContext.PluginSettings.AddRange(legacyPluginSettings.Select(l => l.Migrate()));
- dbContext.SaveChanges();
- }
-
- // ProfileCategories
- if (!dbContext.ProfileCategories.Any())
- {
- logger.Information("Migrating profile categories");
- List legacyProfileCategories = repository.Query().ToList();
- ILiteStorage profileIcons = repository.Database.GetStorage("profileIcons");
- List legacyProfiles = repository.Query().ToList();
- dbContext.ProfileCategories.AddRange(legacyProfileCategories.Select(l => l.Migrate(logger, legacyProfiles, profileIcons)));
- dbContext.SaveChanges();
- }
-
- // Releases
- if (!dbContext.Releases.Any())
- {
- logger.Information("Migrating releases");
- List legacyReleases = repository.Query().ToList();
- dbContext.Releases.AddRange(legacyReleases.Select(l => l.Migrate()));
- dbContext.SaveChanges();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.Storage.Migrator/artemis.db b/src/Artemis.Storage.Migrator/artemis.db
deleted file mode 100644
index 286e00251..000000000
Binary files a/src/Artemis.Storage.Migrator/artemis.db and /dev/null differ
diff --git a/src/Artemis.Storage/ArtemisDbContext.cs b/src/Artemis.Storage/ArtemisDbContext.cs
index 64ebbf963..2a77604fa 100644
--- a/src/Artemis.Storage/ArtemisDbContext.cs
+++ b/src/Artemis.Storage/ArtemisDbContext.cs
@@ -15,8 +15,10 @@ public class ArtemisDbContext : DbContext
public DbSet Devices => Set();
public DbSet Entries => Set();
public DbSet Plugins => Set();
+ public DbSet PluginFeatures => Set();
public DbSet PluginSettings => Set();
public DbSet ProfileCategories => Set();
+ public DbSet ProfileContainers => Set();
public DbSet Releases => Set();
public string DataFolder { get; set; } = string.Empty;
diff --git a/src/Artemis.Storage/Entities/General/ReleaseEntity.cs b/src/Artemis.Storage/Entities/General/ReleaseEntity.cs
index f83efb6f1..47619b3c7 100644
--- a/src/Artemis.Storage/Entities/General/ReleaseEntity.cs
+++ b/src/Artemis.Storage/Entities/General/ReleaseEntity.cs
@@ -1,11 +1,17 @@
using System;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Entities.General;
+[Index(nameof(Version), IsUnique = true)]
+[Index(nameof(InstalledAt))]
public class ReleaseEntity
{
public Guid Id { get; set; }
+ [MaxLength(64)]
public string Version { get; set; } = string.Empty;
+
public DateTimeOffset? InstalledAt { get; set; }
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Entities/Plugins/PluginEntity.cs b/src/Artemis.Storage/Entities/Plugins/PluginEntity.cs
index 0a0ca3b16..faf43f951 100644
--- a/src/Artemis.Storage/Entities/Plugins/PluginEntity.cs
+++ b/src/Artemis.Storage/Entities/Plugins/PluginEntity.cs
@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Entities.Plugins;
///
/// Represents the configuration of a plugin, each plugin has one configuration
///
+[Index(nameof(PluginGuid), IsUnique = true)]
public class PluginEntity
{
public PluginEntity()
@@ -14,6 +17,7 @@ public class PluginEntity
}
public Guid Id { get; set; }
+ public Guid PluginGuid { get; set; }
public bool IsEnabled { get; set; }
public List Features { get; set; }
@@ -25,7 +29,7 @@ public class PluginEntity
public class PluginFeatureEntity
{
public Guid Id { get; set; }
-
+
public string Type { get; set; } = string.Empty;
public bool IsEnabled { get; set; }
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs
index 1d604c28a..b386b34d6 100644
--- a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs
+++ b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs
@@ -1,15 +1,20 @@
using System;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Entities.Plugins;
///
/// Represents the setting of a plugin, a plugin can have multiple settings
///
+[Index(nameof(Name), nameof(PluginGuid), IsUnique = true)]
+[Index(nameof(PluginGuid))]
public class PluginSettingEntity
{
public Guid Id { get; set; }
public Guid PluginGuid { get; set; }
+ [MaxLength(128)]
public string Name { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs
index 02a797011..b7a3c15f4 100644
--- a/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs
+++ b/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs
@@ -1,12 +1,16 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Entities.Profile;
+[Index(nameof(Name), IsUnique = true)]
public class ProfileCategoryEntity
{
public Guid Id { get; set; }
+ [MaxLength(64)]
public string Name { get; set; } = string.Empty;
public bool IsCollapsed { get; set; }
public bool IsSuspended { get; set; }
diff --git a/src/Artemis.Storage/Entities/RawProfileContainer.cs b/src/Artemis.Storage/Entities/RawProfileContainer.cs
new file mode 100644
index 000000000..4638f3e29
--- /dev/null
+++ b/src/Artemis.Storage/Entities/RawProfileContainer.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Artemis.Storage.Entities;
+
+internal class RawProfileContainer
+{
+ public Guid Id { get; set; }
+ public string ProfileConfiguration { get; set; }
+ public string Profile { get; set; }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs
index 374a20941..6500b9b1d 100644
--- a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs
+++ b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
namespace Artemis.Storage.Entities.Surface;
@@ -11,8 +12,12 @@ public class DeviceEntity
Categories = new List();
}
+ [MaxLength(512)]
public string Id { get; set; } = string.Empty;
+
+ [MaxLength(512)]
public string DeviceProvider { get; set; } = string.Empty;
+
public float X { get; set; }
public float Y { get; set; }
public float Rotation { get; set; }
@@ -22,10 +27,16 @@ public class DeviceEntity
public float GreenScale { get; set; }
public float BlueScale { get; set; }
public bool IsEnabled { get; set; }
-
+
public int PhysicalLayout { get; set; }
+
+ [MaxLength(32)]
public string? LogicalLayout { get; set; }
+
+ [MaxLength(64)]
public string? LayoutType { get; set; }
+
+ [MaxLength(512)]
public string? LayoutParameter { get; set; }
public List InputIdentifiers { get; set; }
diff --git a/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs b/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs
index cd828721c..37cdd4cfa 100644
--- a/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs
+++ b/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs
@@ -1,22 +1,23 @@
using System;
using System.Collections.Generic;
-using System.Text.Json.Nodes;
+using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Entities.Workshop;
+[Index(nameof(EntryId), IsUnique = true)]
public class EntryEntity
{
public Guid Id { get; set; }
-
+
public long EntryId { get; set; }
public int EntryType { get; set; }
-
- public string Author { get; set; } = string.Empty;
+
+ public string Author { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public long ReleaseId { get; set; }
public string ReleaseVersion { get; set; } = string.Empty;
public DateTimeOffset InstalledAt { get; set; }
- public Dictionary Metadata { get; set; }
+ public Dictionary? Metadata { get; set; }
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Exceptions/ArtemisStorageException.cs b/src/Artemis.Storage/Exceptions/ArtemisStorageException.cs
new file mode 100644
index 000000000..85e08a3df
--- /dev/null
+++ b/src/Artemis.Storage/Exceptions/ArtemisStorageException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Artemis.Storage.Exceptions;
+
+public class ArtemisStorageException : Exception
+{
+ public ArtemisStorageException(string message) : base(message)
+ {
+ }
+
+ public ArtemisStorageException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Migrations/20240308203921_Initial.Designer.cs b/src/Artemis.Storage/Migrations/20240310201706_Initial.Designer.cs
similarity index 90%
rename from src/Artemis.Storage/Migrations/20240308203921_Initial.Designer.cs
rename to src/Artemis.Storage/Migrations/20240310201706_Initial.Designer.cs
index 14b41beeb..bb62ee588 100644
--- a/src/Artemis.Storage/Migrations/20240308203921_Initial.Designer.cs
+++ b/src/Artemis.Storage/Migrations/20240310201706_Initial.Designer.cs
@@ -11,7 +11,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Artemis.Storage.Migrations
{
[DbContext(typeof(ArtemisDbContext))]
- [Migration("20240308203921_Initial")]
+ [Migration("20240310201706_Initial")]
partial class Initial
{
///
@@ -31,10 +31,16 @@ namespace Artemis.Storage.Migrations
b.Property("Version")
.IsRequired()
+ .HasMaxLength(64)
.HasColumnType("TEXT");
b.HasKey("Id");
+ b.HasIndex("InstalledAt");
+
+ b.HasIndex("Version")
+ .IsUnique();
+
b.ToTable("Releases");
});
@@ -47,8 +53,14 @@ namespace Artemis.Storage.Migrations
b.Property("IsEnabled")
.HasColumnType("INTEGER");
+ b.Property("PluginGuid")
+ .HasColumnType("TEXT");
+
b.HasKey("Id");
+ b.HasIndex("PluginGuid")
+ .IsUnique();
+
b.ToTable("Plugins");
});
@@ -72,7 +84,7 @@ namespace Artemis.Storage.Migrations
b.HasIndex("PluginEntityId");
- b.ToTable("PluginFeatureEntity");
+ b.ToTable("PluginFeatures");
});
modelBuilder.Entity("Artemis.Storage.Entities.Plugins.PluginSettingEntity", b =>
@@ -83,6 +95,7 @@ namespace Artemis.Storage.Migrations
b.Property("Name")
.IsRequired()
+ .HasMaxLength(128)
.HasColumnType("TEXT");
b.Property("PluginGuid")
@@ -94,6 +107,11 @@ namespace Artemis.Storage.Migrations
b.HasKey("Id");
+ b.HasIndex("PluginGuid");
+
+ b.HasIndex("Name", "PluginGuid")
+ .IsUnique();
+
b.ToTable("PluginSettings");
});
@@ -111,6 +129,7 @@ namespace Artemis.Storage.Migrations
b.Property("Name")
.IsRequired()
+ .HasMaxLength(64)
.HasColumnType("TEXT");
b.Property("Order")
@@ -118,6 +137,9 @@ namespace Artemis.Storage.Migrations
b.HasKey("Id");
+ b.HasIndex("Name")
+ .IsUnique();
+
b.ToTable("ProfileCategories");
});
@@ -146,12 +168,13 @@ namespace Artemis.Storage.Migrations
b.HasIndex("ProfileCategoryId");
- b.ToTable("ProfileContainerEntity");
+ b.ToTable("ProfileContainers");
});
modelBuilder.Entity("Artemis.Storage.Entities.Surface.DeviceEntity", b =>
{
b.Property("Id")
+ .HasMaxLength(512)
.HasColumnType("TEXT");
b.Property("BlueScale")
@@ -163,6 +186,7 @@ namespace Artemis.Storage.Migrations
b.Property("DeviceProvider")
.IsRequired()
+ .HasMaxLength(512)
.HasColumnType("TEXT");
b.Property("GreenScale")
@@ -172,12 +196,15 @@ namespace Artemis.Storage.Migrations
.HasColumnType("INTEGER");
b.Property("LayoutParameter")
+ .HasMaxLength(512)
.HasColumnType("TEXT");
b.Property("LayoutType")
+ .HasMaxLength(64)
.HasColumnType("TEXT");
b.Property("LogicalLayout")
+ .HasMaxLength(32)
.HasColumnType("TEXT");
b.Property("PhysicalLayout")
@@ -226,7 +253,6 @@ namespace Artemis.Storage.Migrations
.HasColumnType("TEXT");
b.Property("Metadata")
- .IsRequired()
.HasColumnType("TEXT");
b.Property("Name")
@@ -242,6 +268,9 @@ namespace Artemis.Storage.Migrations
b.HasKey("Id");
+ b.HasIndex("EntryId")
+ .IsUnique();
+
b.ToTable("Entries");
});
diff --git a/src/Artemis.Storage/Migrations/20240308203921_Initial.cs b/src/Artemis.Storage/Migrations/20240310201706_Initial.cs
similarity index 74%
rename from src/Artemis.Storage/Migrations/20240308203921_Initial.cs
rename to src/Artemis.Storage/Migrations/20240310201706_Initial.cs
index 607c92cc6..286f29922 100644
--- a/src/Artemis.Storage/Migrations/20240308203921_Initial.cs
+++ b/src/Artemis.Storage/Migrations/20240310201706_Initial.cs
@@ -15,8 +15,8 @@ namespace Artemis.Storage.Migrations
name: "Devices",
columns: table => new
{
- Id = table.Column(type: "TEXT", nullable: false),
- DeviceProvider = table.Column(type: "TEXT", nullable: false),
+ Id = table.Column(type: "TEXT", maxLength: 512, nullable: false),
+ DeviceProvider = table.Column(type: "TEXT", maxLength: 512, nullable: false),
X = table.Column(type: "REAL", nullable: false),
Y = table.Column(type: "REAL", nullable: false),
Rotation = table.Column(type: "REAL", nullable: false),
@@ -27,9 +27,9 @@ namespace Artemis.Storage.Migrations
BlueScale = table.Column(type: "REAL", nullable: false),
IsEnabled = table.Column(type: "INTEGER", nullable: false),
PhysicalLayout = table.Column(type: "INTEGER", nullable: false),
- LogicalLayout = table.Column(type: "TEXT", nullable: true),
- LayoutType = table.Column(type: "TEXT", nullable: true),
- LayoutParameter = table.Column(type: "TEXT", nullable: true),
+ LogicalLayout = table.Column(type: "TEXT", maxLength: 32, nullable: true),
+ LayoutType = table.Column(type: "TEXT", maxLength: 64, nullable: true),
+ LayoutParameter = table.Column(type: "TEXT", maxLength: 512, nullable: true),
Categories = table.Column(type: "TEXT", nullable: false),
InputIdentifiers = table.Column(type: "TEXT", nullable: false),
InputMappings = table.Column(type: "TEXT", nullable: false)
@@ -51,7 +51,7 @@ namespace Artemis.Storage.Migrations
ReleaseId = table.Column(type: "INTEGER", nullable: false),
ReleaseVersion = table.Column(type: "TEXT", nullable: false),
InstalledAt = table.Column(type: "TEXT", nullable: false),
- Metadata = table.Column(type: "TEXT", nullable: false)
+ Metadata = table.Column(type: "TEXT", nullable: true)
},
constraints: table =>
{
@@ -63,6 +63,7 @@ namespace Artemis.Storage.Migrations
columns: table => new
{
Id = table.Column(type: "TEXT", nullable: false),
+ PluginGuid = table.Column(type: "TEXT", nullable: false),
IsEnabled = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
@@ -76,7 +77,7 @@ namespace Artemis.Storage.Migrations
{
Id = table.Column(type: "TEXT", nullable: false),
PluginGuid = table.Column(type: "TEXT", nullable: false),
- Name = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", maxLength: 128, nullable: false),
Value = table.Column(type: "TEXT", nullable: false)
},
constraints: table =>
@@ -89,7 +90,7 @@ namespace Artemis.Storage.Migrations
columns: table => new
{
Id = table.Column(type: "TEXT", nullable: false),
- Name = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", maxLength: 64, nullable: false),
IsCollapsed = table.Column(type: "INTEGER", nullable: false),
IsSuspended = table.Column(type: "INTEGER", nullable: false),
Order = table.Column(type: "INTEGER", nullable: false)
@@ -104,7 +105,7 @@ namespace Artemis.Storage.Migrations
columns: table => new
{
Id = table.Column(type: "TEXT", nullable: false),
- Version = table.Column(type: "TEXT", nullable: false),
+ Version = table.Column(type: "TEXT", maxLength: 64, nullable: false),
InstalledAt = table.Column(type: "TEXT", nullable: true)
},
constraints: table =>
@@ -113,7 +114,7 @@ namespace Artemis.Storage.Migrations
});
migrationBuilder.CreateTable(
- name: "PluginFeatureEntity",
+ name: "PluginFeatures",
columns: table => new
{
Id = table.Column(type: "TEXT", nullable: false),
@@ -123,16 +124,16 @@ namespace Artemis.Storage.Migrations
},
constraints: table =>
{
- table.PrimaryKey("PK_PluginFeatureEntity", x => x.Id);
+ table.PrimaryKey("PK_PluginFeatures", x => x.Id);
table.ForeignKey(
- name: "FK_PluginFeatureEntity_Plugins_PluginEntityId",
+ name: "FK_PluginFeatures_Plugins_PluginEntityId",
column: x => x.PluginEntityId,
principalTable: "Plugins",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
- name: "ProfileContainerEntity",
+ name: "ProfileContainers",
columns: table => new
{
Id = table.Column(type: "TEXT", nullable: false),
@@ -143,9 +144,9 @@ namespace Artemis.Storage.Migrations
},
constraints: table =>
{
- table.PrimaryKey("PK_ProfileContainerEntity", x => x.Id);
+ table.PrimaryKey("PK_ProfileContainers", x => x.Id);
table.ForeignKey(
- name: "FK_ProfileContainerEntity_ProfileCategories_ProfileCategoryId",
+ name: "FK_ProfileContainers_ProfileCategories_ProfileCategoryId",
column: x => x.ProfileCategoryId,
principalTable: "ProfileCategories",
principalColumn: "Id",
@@ -153,14 +154,54 @@ namespace Artemis.Storage.Migrations
});
migrationBuilder.CreateIndex(
- name: "IX_PluginFeatureEntity_PluginEntityId",
- table: "PluginFeatureEntity",
+ name: "IX_Entries_EntryId",
+ table: "Entries",
+ column: "EntryId",
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_PluginFeatures_PluginEntityId",
+ table: "PluginFeatures",
column: "PluginEntityId");
migrationBuilder.CreateIndex(
- name: "IX_ProfileContainerEntity_ProfileCategoryId",
- table: "ProfileContainerEntity",
+ name: "IX_Plugins_PluginGuid",
+ table: "Plugins",
+ column: "PluginGuid",
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_PluginSettings_Name_PluginGuid",
+ table: "PluginSettings",
+ columns: new[] { "Name", "PluginGuid" },
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_PluginSettings_PluginGuid",
+ table: "PluginSettings",
+ column: "PluginGuid");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ProfileCategories_Name",
+ table: "ProfileCategories",
+ column: "Name",
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ProfileContainers_ProfileCategoryId",
+ table: "ProfileContainers",
column: "ProfileCategoryId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Releases_InstalledAt",
+ table: "Releases",
+ column: "InstalledAt");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Releases_Version",
+ table: "Releases",
+ column: "Version",
+ unique: true);
}
///
@@ -173,13 +214,13 @@ namespace Artemis.Storage.Migrations
name: "Entries");
migrationBuilder.DropTable(
- name: "PluginFeatureEntity");
+ name: "PluginFeatures");
migrationBuilder.DropTable(
name: "PluginSettings");
migrationBuilder.DropTable(
- name: "ProfileContainerEntity");
+ name: "ProfileContainers");
migrationBuilder.DropTable(
name: "Releases");
diff --git a/src/Artemis.Storage/Migrations/ArtemisDbContextModelSnapshot.cs b/src/Artemis.Storage/Migrations/ArtemisDbContextModelSnapshot.cs
index bd8df8c96..270d88797 100644
--- a/src/Artemis.Storage/Migrations/ArtemisDbContextModelSnapshot.cs
+++ b/src/Artemis.Storage/Migrations/ArtemisDbContextModelSnapshot.cs
@@ -28,10 +28,16 @@ namespace Artemis.Storage.Migrations
b.Property("Version")
.IsRequired()
+ .HasMaxLength(64)
.HasColumnType("TEXT");
b.HasKey("Id");
+ b.HasIndex("InstalledAt");
+
+ b.HasIndex("Version")
+ .IsUnique();
+
b.ToTable("Releases");
});
@@ -44,8 +50,14 @@ namespace Artemis.Storage.Migrations
b.Property("IsEnabled")
.HasColumnType("INTEGER");
+ b.Property("PluginGuid")
+ .HasColumnType("TEXT");
+
b.HasKey("Id");
+ b.HasIndex("PluginGuid")
+ .IsUnique();
+
b.ToTable("Plugins");
});
@@ -69,7 +81,7 @@ namespace Artemis.Storage.Migrations
b.HasIndex("PluginEntityId");
- b.ToTable("PluginFeatureEntity");
+ b.ToTable("PluginFeatures");
});
modelBuilder.Entity("Artemis.Storage.Entities.Plugins.PluginSettingEntity", b =>
@@ -80,6 +92,7 @@ namespace Artemis.Storage.Migrations
b.Property("Name")
.IsRequired()
+ .HasMaxLength(128)
.HasColumnType("TEXT");
b.Property("PluginGuid")
@@ -91,6 +104,11 @@ namespace Artemis.Storage.Migrations
b.HasKey("Id");
+ b.HasIndex("PluginGuid");
+
+ b.HasIndex("Name", "PluginGuid")
+ .IsUnique();
+
b.ToTable("PluginSettings");
});
@@ -108,6 +126,7 @@ namespace Artemis.Storage.Migrations
b.Property("Name")
.IsRequired()
+ .HasMaxLength(64)
.HasColumnType("TEXT");
b.Property("Order")
@@ -115,6 +134,9 @@ namespace Artemis.Storage.Migrations
b.HasKey("Id");
+ b.HasIndex("Name")
+ .IsUnique();
+
b.ToTable("ProfileCategories");
});
@@ -143,12 +165,13 @@ namespace Artemis.Storage.Migrations
b.HasIndex("ProfileCategoryId");
- b.ToTable("ProfileContainerEntity");
+ b.ToTable("ProfileContainers");
});
modelBuilder.Entity("Artemis.Storage.Entities.Surface.DeviceEntity", b =>
{
b.Property("Id")
+ .HasMaxLength(512)
.HasColumnType("TEXT");
b.Property("BlueScale")
@@ -160,6 +183,7 @@ namespace Artemis.Storage.Migrations
b.Property("DeviceProvider")
.IsRequired()
+ .HasMaxLength(512)
.HasColumnType("TEXT");
b.Property("GreenScale")
@@ -169,12 +193,15 @@ namespace Artemis.Storage.Migrations
.HasColumnType("INTEGER");
b.Property("LayoutParameter")
+ .HasMaxLength(512)
.HasColumnType("TEXT");
b.Property("LayoutType")
+ .HasMaxLength(64)
.HasColumnType("TEXT");
b.Property("LogicalLayout")
+ .HasMaxLength(32)
.HasColumnType("TEXT");
b.Property("PhysicalLayout")
@@ -223,7 +250,6 @@ namespace Artemis.Storage.Migrations
.HasColumnType("TEXT");
b.Property("Metadata")
- .IsRequired()
.HasColumnType("TEXT");
b.Property("Name")
@@ -239,6 +265,9 @@ namespace Artemis.Storage.Migrations
b.HasKey("Id");
+ b.HasIndex("EntryId")
+ .IsUnique();
+
b.ToTable("Entries");
});
diff --git a/src/Artemis.Storage/Repositories/DeviceRepository.cs b/src/Artemis.Storage/Repositories/DeviceRepository.cs
index 28387fa6e..2eb7098c2 100644
--- a/src/Artemis.Storage/Repositories/DeviceRepository.cs
+++ b/src/Artemis.Storage/Repositories/DeviceRepository.cs
@@ -1,43 +1,50 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using Artemis.Storage.Entities.Surface;
using Artemis.Storage.Repositories.Interfaces;
namespace Artemis.Storage.Repositories;
-internal class DeviceRepository : IDeviceRepository
+internal class DeviceRepository(Func getContext) : IDeviceRepository
{
- private readonly ArtemisDbContext _dbContext;
-
- public DeviceRepository(ArtemisDbContext dbContext)
- {
- _dbContext = dbContext;
- }
-
public void Add(DeviceEntity deviceEntity)
{
- _dbContext.Devices.Add(deviceEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Devices.Add(deviceEntity);
+ dbContext.SaveChanges();
}
public void Remove(DeviceEntity deviceEntity)
{
- _dbContext.Devices.Remove(deviceEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Devices.Remove(deviceEntity);
+ dbContext.SaveChanges();
}
public DeviceEntity? Get(string id)
{
- return _dbContext.Devices.FirstOrDefault(d => d.Id == id);
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Devices.FirstOrDefault(d => d.Id == id);
}
public IEnumerable GetAll()
{
- return _dbContext.Devices;
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Devices;
}
-
- public void SaveChanges()
+
+ public void Save(DeviceEntity deviceEntity)
{
- _dbContext.SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Update(deviceEntity);
+ dbContext.SaveChanges();
+ }
+
+ public void SaveRange(IEnumerable deviceEntities)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.UpdateRange(deviceEntities);
+ dbContext.SaveChanges();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/EntryRepository.cs b/src/Artemis.Storage/Repositories/EntryRepository.cs
index e378ace28..a901e637d 100644
--- a/src/Artemis.Storage/Repositories/EntryRepository.cs
+++ b/src/Artemis.Storage/Repositories/EntryRepository.cs
@@ -6,44 +6,44 @@ using Artemis.Storage.Repositories.Interfaces;
namespace Artemis.Storage.Repositories;
-internal class EntryRepository : IEntryRepository
+internal class EntryRepository(Func getContext) : IEntryRepository
{
- private readonly ArtemisDbContext _dbContext;
-
- public EntryRepository(ArtemisDbContext dbContext)
- {
- _dbContext = dbContext;
- }
-
public void Add(EntryEntity entryEntity)
{
- _dbContext.Entries.Add(entryEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Entries.Add(entryEntity);
+ dbContext.SaveChanges();
}
public void Remove(EntryEntity entryEntity)
{
- _dbContext.Entries.Remove(entryEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Entries.Remove(entryEntity);
+ dbContext.SaveChanges();
}
public EntryEntity? Get(Guid id)
{
- return _dbContext.Entries.FirstOrDefault(s => s.Id == id);
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Entries.FirstOrDefault(s => s.Id == id);
}
public EntryEntity? GetByEntryId(long entryId)
{
- return _dbContext.Entries.FirstOrDefault(s => s.EntryId == entryId);
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Entries.FirstOrDefault(s => s.EntryId == entryId);
}
public IEnumerable GetAll()
{
- return _dbContext.Entries;
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Entries;
}
-
- public void SaveChanges()
+
+ public void Save(EntryEntity entryEntity)
{
- _dbContext.SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Update(entryEntity);
+ dbContext.SaveChanges();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs
index 960f61d66..f2a77e3d2 100644
--- a/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs
+++ b/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs
@@ -9,5 +9,6 @@ public interface IDeviceRepository : IRepository
void Remove(DeviceEntity deviceEntity);
DeviceEntity? Get(string id);
IEnumerable GetAll();
- void SaveChanges();
+ void Save(DeviceEntity deviceEntity);
+ void SaveRange(IEnumerable deviceEntities);
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs
index f1146de9f..46722068e 100644
--- a/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs
+++ b/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs
@@ -11,5 +11,5 @@ public interface IEntryRepository : IRepository
EntryEntity? Get(Guid id);
EntryEntity? GetByEntryId(long entryId);
IEnumerable GetAll();
- void SaveChanges();
+ void Save(EntryEntity entryEntity);
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
index 87e3e48e4..cb25caf5d 100644
--- a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
+++ b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
@@ -5,10 +5,9 @@ namespace Artemis.Storage.Repositories.Interfaces;
public interface IPluginRepository : IRepository
{
- void AddPlugin(PluginEntity pluginEntity);
- PluginEntity? GetPluginByGuid(Guid pluginGuid);
- void AddSetting(PluginSettingEntity pluginSettingEntity);
+ PluginEntity? GetPluginByPluginGuid(Guid pluginGuid);
+ void SaveSetting(PluginSettingEntity pluginSettingEntity);
+ void SavePlugin(PluginEntity pluginEntity);
PluginSettingEntity? GetSettingByNameAndGuid(string name, Guid pluginGuid);
void RemoveSettings(Guid pluginGuid);
- void SaveChanges();
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs
index cf3dccee6..533e8990e 100644
--- a/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs
+++ b/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs
@@ -12,5 +12,6 @@ public interface IProfileCategoryRepository : IRepository
List GetAll();
ProfileCategoryEntity? Get(Guid id);
bool IsUnique(string name, Guid? id);
- void SaveChanges();
+ void Save(ProfileCategoryEntity profileCategoryEntity);
+ void SaveRange(List profileCategoryEntities);
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs
new file mode 100644
index 000000000..bc26090a5
--- /dev/null
+++ b/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using System.Text.Json.Nodes;
+using Artemis.Storage.Entities.Profile;
+
+namespace Artemis.Storage.Repositories.Interfaces;
+
+public interface IProfileRepository : IRepository
+{
+ void Add(ProfileContainerEntity profileContainerEntity);
+ void Remove(ProfileContainerEntity profileContainerEntity);
+ void Save(ProfileContainerEntity profileContainerEntity);
+ void SaveRange(List profileContainerEntities);
+ void MigrateProfiles();
+ void MigrateProfile(JsonObject? configurationJson, JsonObject? profileJson);
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IReleaseRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IReleaseRepository.cs
new file mode 100644
index 000000000..9404bf8dd
--- /dev/null
+++ b/src/Artemis.Storage/Repositories/Interfaces/IReleaseRepository.cs
@@ -0,0 +1,9 @@
+using Artemis.Storage.Entities.General;
+
+namespace Artemis.Storage.Repositories.Interfaces;
+
+public interface IReleaseRepository : IRepository
+{
+ bool SaveVersionInstallDate(string version);
+ ReleaseEntity? GetPreviousInstalledVersion();
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/PluginRepository.cs b/src/Artemis.Storage/Repositories/PluginRepository.cs
index 8c53d776c..abb335893 100644
--- a/src/Artemis.Storage/Repositories/PluginRepository.cs
+++ b/src/Artemis.Storage/Repositories/PluginRepository.cs
@@ -6,44 +6,39 @@ using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Repositories;
-internal class PluginRepository : IPluginRepository
+internal class PluginRepository(Func getContext) : IPluginRepository
{
- private readonly ArtemisDbContext _dbContext;
-
- public PluginRepository(ArtemisDbContext dbContext)
+ public PluginEntity? GetPluginByPluginGuid(Guid pluginGuid)
{
- _dbContext = dbContext;
- }
-
- public void AddPlugin(PluginEntity pluginEntity)
- {
- _dbContext.Plugins.Add(pluginEntity);
- SaveChanges();
- }
-
- public PluginEntity? GetPluginByGuid(Guid pluginGuid)
- {
- return _dbContext.Plugins.Include(p => p.Features).FirstOrDefault(p => p.Id == pluginGuid);
- }
-
- public void AddSetting(PluginSettingEntity pluginSettingEntity)
- {
- _dbContext.PluginSettings.Add(pluginSettingEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Plugins.Include(p => p.Features).FirstOrDefault(p => p.PluginGuid == pluginGuid);
}
public PluginSettingEntity? GetSettingByNameAndGuid(string name, Guid pluginGuid)
{
- return _dbContext.PluginSettings.FirstOrDefault(p => p.Name == name && p.PluginGuid == pluginGuid);
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.PluginSettings.FirstOrDefault(p => p.Name == name && p.PluginGuid == pluginGuid);
}
-
+
public void RemoveSettings(Guid pluginGuid)
{
- _dbContext.PluginSettings.RemoveRange(_dbContext.PluginSettings.Where(s => s.PluginGuid == pluginGuid));
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.PluginSettings.RemoveRange(dbContext.PluginSettings.Where(s => s.PluginGuid == pluginGuid));
+ dbContext.SaveChanges();
}
- public void SaveChanges()
+ public void SaveSetting(PluginSettingEntity pluginSettingEntity)
{
- _dbContext.SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.PluginSettings.Update(pluginSettingEntity);
+ dbContext.SaveChanges();
}
+
+ public void SavePlugin(PluginEntity pluginEntity)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Update(pluginEntity);
+ dbContext.SaveChanges();
+ }
+
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs b/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs
index 7d0ef11bc..90e53c731 100644
--- a/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs
+++ b/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs
@@ -7,47 +7,63 @@ using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Repositories;
-internal class ProfileCategoryRepository : IProfileCategoryRepository
+internal class ProfileCategoryRepository(Func getContext, IProfileRepository profileRepository) : IProfileCategoryRepository
{
- private readonly ArtemisDbContext _dbContext;
-
- public ProfileCategoryRepository(ArtemisDbContext dbContext)
- {
- _dbContext = dbContext;
- }
+ private bool _migratedProfiles;
public void Add(ProfileCategoryEntity profileCategoryEntity)
{
- _dbContext.ProfileCategories.Add(profileCategoryEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.ProfileCategories.Add(profileCategoryEntity);
+ dbContext.SaveChanges();
}
public void Remove(ProfileCategoryEntity profileCategoryEntity)
{
- _dbContext.ProfileCategories.Remove(profileCategoryEntity);
- SaveChanges();
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.ProfileCategories.Remove(profileCategoryEntity);
+ dbContext.SaveChanges();
}
public List GetAll()
{
- return _dbContext.ProfileCategories.Include(c => c.ProfileConfigurations).ToList();
+ if (!_migratedProfiles)
+ {
+ profileRepository.MigrateProfiles();
+ _migratedProfiles = true;
+ }
+
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.ProfileCategories.Include(c => c.ProfileConfigurations).ToList();
}
public ProfileCategoryEntity? Get(Guid id)
{
- return _dbContext.ProfileCategories.Include(c => c.ProfileConfigurations).FirstOrDefault(c => c.Id == id);
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.ProfileCategories.Include(c => c.ProfileConfigurations).FirstOrDefault(c => c.Id == id);
+ }
+
+ public void Save(ProfileCategoryEntity profileCategoryEntity)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Update(profileCategoryEntity);
+ dbContext.SaveChanges();
+ }
+
+ public void SaveRange(List profileCategoryEntities)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.UpdateRange(profileCategoryEntities);
+ dbContext.SaveChanges();
}
public bool IsUnique(string name, Guid? id)
{
+ using ArtemisDbContext dbContext = getContext();
+
name = name.Trim();
- if (id == null)
- return _dbContext.ProfileCategories.Any(p => p.Name == name);
- return _dbContext.ProfileCategories.Any(p => p.Name == name && p.Id != id.Value);
- }
-
- public void SaveChanges()
- {
- _dbContext.SaveChanges();
+ return id == null
+ ? dbContext.ProfileCategories.Any(p => p.Name == name)
+ : dbContext.ProfileCategories.Any(p => p.Name == name && p.Id != id.Value);
}
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/ProfileRepository.cs b/src/Artemis.Storage/Repositories/ProfileRepository.cs
new file mode 100644
index 000000000..78c9ca6a0
--- /dev/null
+++ b/src/Artemis.Storage/Repositories/ProfileRepository.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json.Nodes;
+using Artemis.Storage.Entities;
+using Artemis.Storage.Entities.Profile;
+using Artemis.Storage.Exceptions;
+using Artemis.Storage.Migrations;
+using Artemis.Storage.Repositories.Interfaces;
+using Microsoft.EntityFrameworkCore;
+
+namespace Artemis.Storage.Repositories;
+
+public class ProfileRepository(Func getContext, List profileMigrators) : IProfileRepository
+{
+ public void Add(ProfileContainerEntity profileContainerEntity)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.ProfileContainers.Add(profileContainerEntity);
+ dbContext.SaveChanges();
+ }
+
+ public void Remove(ProfileContainerEntity profileContainerEntity)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.ProfileContainers.Remove(profileContainerEntity);
+ dbContext.SaveChanges();
+ }
+
+ public void Save(ProfileContainerEntity profileContainerEntity)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.Update(profileContainerEntity);
+ dbContext.SaveChanges();
+ }
+
+ public void SaveRange(List profileContainerEntities)
+ {
+ using ArtemisDbContext dbContext = getContext();
+ dbContext.UpdateRange(profileContainerEntities);
+ dbContext.SaveChanges();
+ }
+
+ public void MigrateProfiles()
+ {
+ using ArtemisDbContext dbContext = getContext();
+ int max = profileMigrators.Max(m => m.Version);
+
+ // Query the ProfileContainerEntity table directly, grabbing the ID, profile, and configuration
+ List containers = dbContext.Database
+ .SqlQueryRaw("SELECT Id, Profile, ProfileConfiguration FROM ProfileContainers WHERE json_extract(ProfileConfiguration, '$.Version') < {0}", max)
+ .ToList();
+
+ foreach (RawProfileContainer rawProfileContainer in containers)
+ {
+ JsonObject? profileConfiguration = JsonNode.Parse(rawProfileContainer.ProfileConfiguration)?.AsObject();
+ JsonObject? profile = JsonNode.Parse(rawProfileContainer.Profile)?.AsObject();
+
+ if (profileConfiguration == null || profile == null)
+ throw new ArtemisStorageException("Failed to parse profile or profile configuration");
+
+ MigrateProfile(profileConfiguration, profile);
+ rawProfileContainer.Profile = profile.ToString();
+ rawProfileContainer.ProfileConfiguration = profileConfiguration.ToString();
+
+ // Write the updated containers back to the database
+ dbContext.Database.ExecuteSqlRaw(
+ "UPDATE ProfileContainers SET Profile = {0}, ProfileConfiguration = {1} WHERE Id = {2}",
+ rawProfileContainer.Profile,
+ rawProfileContainer.ProfileConfiguration,
+ rawProfileContainer.Id);
+ }
+ }
+
+ public void MigrateProfile(JsonObject? configurationJson, JsonObject? profileJson)
+ {
+ if (configurationJson == null || profileJson == null)
+ return;
+
+ configurationJson["Version"] ??= 0;
+
+ foreach (IProfileMigration profileMigrator in profileMigrators.OrderBy(m => m.Version))
+ {
+ if (profileMigrator.Version <= configurationJson["Version"]!.GetValue())
+ continue;
+
+ profileMigrator.Migrate(configurationJson, profileJson);
+ configurationJson["Version"] = profileMigrator.Version;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/ReleaseRepository.cs b/src/Artemis.Storage/Repositories/ReleaseRepository.cs
index d7e320919..16f5dd7a6 100644
--- a/src/Artemis.Storage/Repositories/ReleaseRepository.cs
+++ b/src/Artemis.Storage/Repositories/ReleaseRepository.cs
@@ -5,34 +5,24 @@ using Artemis.Storage.Repositories.Interfaces;
namespace Artemis.Storage.Repositories;
-public class ReleaseRepository : IReleaseRepository
+public class ReleaseRepository(Func getContext) : IReleaseRepository
{
- private readonly ArtemisDbContext _dbContext;
-
- public ReleaseRepository(ArtemisDbContext dbContext)
- {
- _dbContext = dbContext;
- }
-
public bool SaveVersionInstallDate(string version)
{
- ReleaseEntity? release = _dbContext.Releases.FirstOrDefault(r => r.Version == version);
+ using ArtemisDbContext dbContext = getContext();
+
+ ReleaseEntity? release = dbContext.Releases.FirstOrDefault(r => r.Version == version);
if (release != null)
return false;
- _dbContext.Releases.Add(new ReleaseEntity {Version = version, InstalledAt = DateTimeOffset.UtcNow});
- _dbContext.SaveChanges();
+ dbContext.Releases.Add(new ReleaseEntity {Version = version, InstalledAt = DateTimeOffset.UtcNow});
+ dbContext.SaveChanges();
return true;
}
public ReleaseEntity? GetPreviousInstalledVersion()
{
- return _dbContext.Releases.OrderByDescending(r => r.InstalledAt).Skip(1).FirstOrDefault();
+ using ArtemisDbContext dbContext = getContext();
+ return dbContext.Releases.OrderByDescending(r => r.InstalledAt).Skip(1).FirstOrDefault();
}
-}
-
-public interface IReleaseRepository : IRepository
-{
- bool SaveVersionInstallDate(string version);
- ReleaseEntity? GetPreviousInstalledVersion();
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Linux/App.axaml.cs b/src/Artemis.UI.Linux/App.axaml.cs
index 88f0f8179..dbba1fb2f 100644
--- a/src/Artemis.UI.Linux/App.axaml.cs
+++ b/src/Artemis.UI.Linux/App.axaml.cs
@@ -1,5 +1,6 @@
using System;
using Artemis.Core.Services;
+using Artemis.Storage.Legacy;
using Artemis.UI.Linux.DryIoc;
using Artemis.UI.Linux.Providers.Input;
using Avalonia;
@@ -20,7 +21,10 @@ public class App : Application
public override void Initialize()
{
_container = ArtemisBootstrapper.Bootstrap(this, c => c.RegisterProviders());
+
Program.CreateLogger(_container);
+ LegacyMigrationService.MigrateToSqlite(_container);
+
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this);
}
diff --git a/src/Artemis.UI.Linux/Artemis.UI.Linux.csproj b/src/Artemis.UI.Linux/Artemis.UI.Linux.csproj
index c41b62a40..ed8f08fda 100644
--- a/src/Artemis.UI.Linux/Artemis.UI.Linux.csproj
+++ b/src/Artemis.UI.Linux/Artemis.UI.Linux.csproj
@@ -17,6 +17,7 @@
+
diff --git a/src/Artemis.UI.MacOS/App.axaml.cs b/src/Artemis.UI.MacOS/App.axaml.cs
index 0d81b318d..800bb523f 100644
--- a/src/Artemis.UI.MacOS/App.axaml.cs
+++ b/src/Artemis.UI.MacOS/App.axaml.cs
@@ -1,3 +1,4 @@
+using Artemis.Storage.Legacy;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@@ -14,7 +15,10 @@ public class App : Application
public override void Initialize()
{
_container = ArtemisBootstrapper.Bootstrap(this);
+
Program.CreateLogger(_container);
+ LegacyMigrationService.MigrateToSqlite(_container);
+
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this);
}
diff --git a/src/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj b/src/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj
index d762afde1..f322b73d7 100644
--- a/src/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj
+++ b/src/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj
@@ -16,6 +16,7 @@
+
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
index bf6734a2a..42faecb23 100644
--- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
+++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
@@ -21,6 +21,7 @@
+
diff --git a/src/Artemis.UI.Windows/App.axaml.cs b/src/Artemis.UI.Windows/App.axaml.cs
index 41ed8e923..66d5aac1b 100644
--- a/src/Artemis.UI.Windows/App.axaml.cs
+++ b/src/Artemis.UI.Windows/App.axaml.cs
@@ -7,6 +7,7 @@ using System.Net.Http;
using System.Threading;
using Artemis.Core;
using Artemis.Core.Services;
+using Artemis.Storage.Legacy;
using Artemis.UI.Windows.DryIoc;
using Artemis.UI.Windows.Providers.Input;
using Avalonia;
@@ -34,7 +35,10 @@ public class App : Application
}
_container = ArtemisBootstrapper.Bootstrap(this, c => c.RegisterProviders());
+
Program.CreateLogger(_container);
+ LegacyMigrationService.MigrateToSqlite(_container);
+
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this);
}
diff --git a/src/Artemis.UI.Windows/Artemis.UI.Windows.csproj b/src/Artemis.UI.Windows/Artemis.UI.Windows.csproj
index 52a121156..f74f2bd4b 100644
--- a/src/Artemis.UI.Windows/Artemis.UI.Windows.csproj
+++ b/src/Artemis.UI.Windows/Artemis.UI.Windows.csproj
@@ -30,6 +30,7 @@
+
diff --git a/src/Artemis.UI/Services/Updating/UpdateService.cs b/src/Artemis.UI/Services/Updating/UpdateService.cs
index deb6484ea..a6259db37 100644
--- a/src/Artemis.UI/Services/Updating/UpdateService.cs
+++ b/src/Artemis.UI/Services/Updating/UpdateService.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.Storage.Repositories;
+using Artemis.Storage.Repositories.Interfaces;
using Artemis.UI.Exceptions;
using Artemis.UI.Shared.Services.MainWindow;
using Artemis.WebClient.Updating;
diff --git a/src/Artemis.WebClient.Workshop/Handlers/InstallationHandlers/Implementations/ProfileEntryInstallationHandler.cs b/src/Artemis.WebClient.Workshop/Handlers/InstallationHandlers/Implementations/ProfileEntryInstallationHandler.cs
index 4ee9e0cb5..1219f84d6 100644
--- a/src/Artemis.WebClient.Workshop/Handlers/InstallationHandlers/Implementations/ProfileEntryInstallationHandler.cs
+++ b/src/Artemis.WebClient.Workshop/Handlers/InstallationHandlers/Implementations/ProfileEntryInstallationHandler.cs
@@ -76,7 +76,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
// Find the profile if still there
ProfileConfiguration? profile = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == profileId);
if (profile != null)
- _profileService.DeleteProfile(profile);
+ _profileService.RemoveProfileConfiguration(profile);
// Remove the release
_workshopService.RemoveInstalledEntry(installedEntry);
diff --git a/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs b/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs
index 3da255d12..95b90ccc5 100644
--- a/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs
+++ b/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs
@@ -171,12 +171,7 @@ public class WorkshopService : IWorkshopService
public void SaveInstalledEntry(InstalledEntry entry)
{
entry.Save();
-
- // Upsert for plebs
- if (entry.Entity.Id == Guid.Empty)
- _entryRepository.Add(entry.Entity);
- else
- _entryRepository.SaveChanges();
+ _entryRepository.Save(entry.Entity);
}
///
diff --git a/src/Artemis.sln b/src/Artemis.sln
index 984eb7997..7f7a038f0 100644
--- a/src/Artemis.sln
+++ b/src/Artemis.sln
@@ -29,7 +29,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.props = Directory.Build.props
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Storage.Migrator", "Artemis.Storage.Migrator\Artemis.Storage.Migrator.csproj", "{D7B0966D-774A-40E4-9455-00C1261ACB6A}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Storage.Legacy", "Artemis.Storage.Legacy\Artemis.Storage.Legacy.csproj", "{D7B0966D-774A-40E4-9455-00C1261ACB6A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 3c9d036db..f997dd00e 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -25,12 +25,13 @@
+
-
+