mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Storage - Clean up legacy project and refactor repositories to use short lived DB contexts
This commit is contained in:
parent
d4e4d52f84
commit
4bae9e89cf
@ -40,7 +40,7 @@
|
||||
<PackageReference Include="EmbedIO" />
|
||||
<PackageReference Include="HidSharp" />
|
||||
<PackageReference Include="Humanizer.Core" />
|
||||
<PackageReference Include="JetBrains.Annotations" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All"/>
|
||||
<PackageReference Include="McMaster.NETCore.Plugins" />
|
||||
<PackageReference Include="RGB.NET.Core" />
|
||||
<PackageReference Include="RGB.NET.Layout" />
|
||||
|
||||
@ -91,7 +91,7 @@ public static class Constants
|
||||
/// <summary>
|
||||
/// The plugin used by core components of Artemis
|
||||
/// </summary>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// A read-only collection containing all primitive numeric types
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -94,7 +94,7 @@ public class PluginSetting<T> : CorePropertyChanged, IPluginSetting
|
||||
return;
|
||||
|
||||
_pluginSettingEntity.Value = CoreJson.Serialize(Value);
|
||||
_pluginRepository.SaveChanges();
|
||||
_pluginRepository.SaveSetting(_pluginSettingEntity);
|
||||
OnSettingSaved();
|
||||
}
|
||||
|
||||
|
||||
@ -31,10 +31,13 @@ public class PluginSettings
|
||||
/// Gets the setting with the provided name. If the setting does not exist yet, it is created.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the setting, can be any serializable type</typeparam>
|
||||
/// <param name="name">The name of the setting</param>
|
||||
/// <param name="name">The name of the setting, may not be longer than 128 characters</param>
|
||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||
public PluginSetting<T> GetSetting<T>(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<T> pluginSetting = new(_pluginRepository, settingEntity);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the setting, can be any serializable type</typeparam>
|
||||
/// <param name="name">The name of the setting</param>
|
||||
/// <param name="name">The name of the setting, may not be longer than 128 characters</param>
|
||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||
/// <returns></returns>
|
||||
PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default);
|
||||
|
||||
@ -54,13 +54,7 @@ public interface IProfileService : IArtemisService
|
||||
/// </summary>
|
||||
/// <param name="profileConfiguration">The profile configuration of the profile to activate.</param>
|
||||
void DeactivateProfile(ProfileConfiguration profileConfiguration);
|
||||
|
||||
/// <summary>
|
||||
/// Permanently deletes the profile of the given <see cref="ProfileConfiguration" />.
|
||||
/// </summary>
|
||||
/// <param name="profileConfiguration">The profile configuration of the profile to delete.</param>
|
||||
void DeleteProfile(ProfileConfiguration profileConfiguration);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves the provided <see cref="ProfileCategory" /> and it's <see cref="ProfileConfiguration" />s but not the
|
||||
/// <see cref="Profile" />s themselves.
|
||||
|
||||
@ -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<ArtemisKeyboardKeyEventArgs> _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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DeleteProfile(ProfileConfiguration profileConfiguration)
|
||||
{
|
||||
DeactivateProfile(profileConfiguration);
|
||||
|
||||
ProfileCategory category = profileConfiguration.Category;
|
||||
|
||||
category.RemoveProfileConfiguration(profileConfiguration);
|
||||
category.Entity.ProfileConfigurations.Remove(profileConfiguration.Entity);
|
||||
|
||||
_profileCategoryRepository.SaveChanges();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveProfileCategory(ProfileCategory profileCategory)
|
||||
{
|
||||
profileCategory.Save();
|
||||
_profileCategoryRepository.SaveChanges();
|
||||
_profileCategoryRepository.Save(profileCategory.Entity);
|
||||
ProfileCategories = new ReadOnlyCollection<ProfileCategory>(ProfileCategories.OrderBy(c => c.Order).ToList());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -393,7 +378,7 @@ internal class ProfileService : IProfileService
|
||||
JsonObject? profileJson = CoreJson.Deserialize<JsonObject>(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<ProfileConfigurationEntity>(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<int>())
|
||||
continue;
|
||||
|
||||
profileMigrator.Migrate(configurationJson, profileJson);
|
||||
configurationJson["Version"] = profileMigrator.Version;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Populates all missing LEDs on all currently active profiles
|
||||
/// </summary>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
@ -13,8 +12,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
|
||||
<PackageReference Include="LiteDB" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@ -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()
|
||||
{
|
||||
@ -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; }
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
namespace Artemis.Storage.Migrator.Legacy.Entities.Plugins;
|
||||
namespace Artemis.Storage.Legacy.Entities.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the configuration of a plugin, each plugin has one configuration
|
||||
/// </summary>
|
||||
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
|
||||
/// <summary>
|
||||
/// Represents the configuration of a plugin feature, each feature has one configuration
|
||||
/// </summary>
|
||||
public class PluginFeatureEntity
|
||||
internal class PluginFeatureEntity
|
||||
{
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public bool IsEnabled { get; set; }
|
||||
@ -1,9 +1,9 @@
|
||||
namespace Artemis.Storage.Migrator.Legacy.Entities.Plugins;
|
||||
namespace Artemis.Storage.Legacy.Entities.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the setting of a plugin, a plugin can have multiple settings
|
||||
/// </summary>
|
||||
public class PluginSettingEntity
|
||||
internal class PluginSettingEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid PluginGuid { get; set; }
|
||||
@ -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; }
|
||||
@ -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; }
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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")]
|
||||
@ -0,0 +1,6 @@
|
||||
namespace Artemis.Storage.Legacy.Entities.Profile.AdaptionHints;
|
||||
|
||||
internal class KeyboardSectionAdaptionHintEntity : IAdaptionHintEntity
|
||||
{
|
||||
public int Section { get; set; }
|
||||
}
|
||||
@ -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; }
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
|
||||
|
||||
internal class AlwaysOnConditionEntity : IConditionEntity;
|
||||
@ -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; }
|
||||
@ -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")]
|
||||
@ -0,0 +1,3 @@
|
||||
namespace Artemis.Storage.Legacy.Entities.Profile.Conditions;
|
||||
|
||||
internal class PlayOnceConditionEntity : IConditionEntity;
|
||||
@ -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; }
|
||||
}
|
||||
@ -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; }
|
||||
}
|
||||
@ -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; }
|
||||
@ -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; }
|
||||
@ -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; }
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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()
|
||||
{
|
||||
@ -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;
|
||||
@ -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()
|
||||
{
|
||||
@ -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()
|
||||
{
|
||||
@ -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()
|
||||
{
|
||||
@ -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()
|
||||
{
|
||||
@ -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; }
|
||||
|
||||
@ -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; }
|
||||
@ -0,0 +1,7 @@
|
||||
namespace Artemis.Storage.Legacy.Entities.Profile;
|
||||
|
||||
internal class ProfileConfigurationHotkeyEntity
|
||||
{
|
||||
public int? Key { get; set; }
|
||||
public int? Modifiers { get; set; }
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
@ -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;
|
||||
@ -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<PropertyEntity> Properties { get; set; } = new();
|
||||
@ -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; }
|
||||
@ -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;
|
||||
@ -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; }
|
||||
|
||||
163
src/Artemis.Storage.Legacy/LegacyMigrationService.cs
Normal file
163
src/Artemis.Storage.Legacy/LegacyMigrationService.cs
Normal file
@ -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<ILogger>();
|
||||
|
||||
// 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<ArtemisDbContext>();
|
||||
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<DeviceEntity> legacyDevices = repository.Query<DeviceEntity>().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<EntryEntity> legacyEntries = repository.Query<EntryEntity>().ToList();
|
||||
dbContext.Entries.AddRange(legacyEntries.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// Plugins
|
||||
if (!dbContext.Plugins.Any())
|
||||
{
|
||||
logger.Information("Migrating plugins");
|
||||
List<PluginEntity> legacyPlugins = repository.Query<PluginEntity>().ToList();
|
||||
dbContext.Plugins.AddRange(legacyPlugins.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// PluginSettings
|
||||
if (!dbContext.PluginSettings.Any())
|
||||
{
|
||||
logger.Information("Migrating plugin settings");
|
||||
List<PluginSettingEntity> legacyPluginSettings = repository.Query<PluginSettingEntity>().ToList();
|
||||
dbContext.PluginSettings.AddRange(legacyPluginSettings.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// ProfileCategories
|
||||
if (!dbContext.ProfileCategories.Any())
|
||||
{
|
||||
logger.Information("Migrating profile categories");
|
||||
List<ProfileCategoryEntity> legacyProfileCategories = repository.Query<ProfileCategoryEntity>().ToList();
|
||||
ILiteStorage<Guid> profileIcons = repository.Database.GetStorage<Guid>("profileIcons");
|
||||
List<ProfileEntity> legacyProfiles = repository.Query<ProfileEntity>().ToList();
|
||||
dbContext.ProfileCategories.AddRange(legacyProfileCategories.Select(l => l.Migrate(logger, legacyProfiles, profileIcons)));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// Releases
|
||||
if (!dbContext.Releases.Any())
|
||||
{
|
||||
logger.Information("Migrating releases");
|
||||
List<ReleaseEntity> legacyReleases = repository.Query<ReleaseEntity>().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<IStorageMigration> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Artemis.Storage.Migrator.Legacy.Migrations;
|
||||
namespace Artemis.Storage.Legacy.Migrations;
|
||||
|
||||
public interface IProfileMigration
|
||||
{
|
||||
@ -1,6 +1,6 @@
|
||||
using LiteDB;
|
||||
|
||||
namespace Artemis.Storage.Migrator.Legacy.Migrations;
|
||||
namespace Artemis.Storage.Legacy.Migrations;
|
||||
|
||||
public interface IStorageMigration
|
||||
{
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
@ -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");
|
||||
@ -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<BsonDocument> 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)
|
||||
@ -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)
|
||||
@ -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)
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/Artemis.Storage.Legacy/Program.cs
Normal file
22
src/Artemis.Storage.Legacy/Program.cs
Normal file
@ -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<ILogger>();
|
||||
// ArtemisDbContext dbContext = container.Resolve<ArtemisDbContext>();
|
||||
//
|
||||
// logger.Information("Applying pending migrations...");
|
||||
// dbContext.Database.Migrate();
|
||||
// logger.Information("Pending migrations applied");
|
||||
//
|
||||
// MigrationService.MigrateToSqlite(logger, dbContext);
|
||||
@ -1,6 +0,0 @@
|
||||
namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.AdaptionHints;
|
||||
|
||||
public class KeyboardSectionAdaptionHintEntity : IAdaptionHintEntity
|
||||
{
|
||||
public int Section { get; set; }
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
|
||||
|
||||
public class AlwaysOnConditionEntity : IConditionEntity;
|
||||
@ -1,3 +0,0 @@
|
||||
namespace Artemis.Storage.Migrator.Legacy.Entities.Profile.Conditions;
|
||||
|
||||
public class PlayOnceConditionEntity : IConditionEntity;
|
||||
@ -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; }
|
||||
}
|
||||
@ -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; }
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Artemis.Storage.Migrator.Legacy.Entities.Profile;
|
||||
|
||||
public class ProfileConfigurationHotkeyEntity
|
||||
{
|
||||
public int? Key { get; set; }
|
||||
public int? Modifiers { get; set; }
|
||||
}
|
||||
@ -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<IStorageMigration> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<ILogger>();
|
||||
ArtemisDbContext dbContext = container.Resolve<ArtemisDbContext>();
|
||||
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<DeviceEntity> legacyDevices = repository.Query<DeviceEntity>().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<EntryEntity> legacyEntries = repository.Query<EntryEntity>().ToList();
|
||||
dbContext.Entries.AddRange(legacyEntries.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// Plugins
|
||||
if (!dbContext.Plugins.Any())
|
||||
{
|
||||
logger.Information("Migrating plugins");
|
||||
List<PluginEntity> legacyPlugins = repository.Query<PluginEntity>().ToList();
|
||||
dbContext.Plugins.AddRange(legacyPlugins.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// PluginSettings
|
||||
if (!dbContext.PluginSettings.Any())
|
||||
{
|
||||
logger.Information("Migrating plugin settings");
|
||||
List<PluginSettingEntity> legacyPluginSettings = repository.Query<PluginSettingEntity>().ToList();
|
||||
dbContext.PluginSettings.AddRange(legacyPluginSettings.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// ProfileCategories
|
||||
if (!dbContext.ProfileCategories.Any())
|
||||
{
|
||||
logger.Information("Migrating profile categories");
|
||||
List<ProfileCategoryEntity> legacyProfileCategories = repository.Query<ProfileCategoryEntity>().ToList();
|
||||
ILiteStorage<Guid> profileIcons = repository.Database.GetStorage<Guid>("profileIcons");
|
||||
List<ProfileEntity> legacyProfiles = repository.Query<ProfileEntity>().ToList();
|
||||
dbContext.ProfileCategories.AddRange(legacyProfileCategories.Select(l => l.Migrate(logger, legacyProfiles, profileIcons)));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// Releases
|
||||
if (!dbContext.Releases.Any())
|
||||
{
|
||||
logger.Information("Migrating releases");
|
||||
List<ReleaseEntity> legacyReleases = repository.Query<ReleaseEntity>().ToList();
|
||||
dbContext.Releases.AddRange(legacyReleases.Select(l => l.Migrate()));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -15,8 +15,10 @@ public class ArtemisDbContext : DbContext
|
||||
public DbSet<DeviceEntity> Devices => Set<DeviceEntity>();
|
||||
public DbSet<EntryEntity> Entries => Set<EntryEntity>();
|
||||
public DbSet<PluginEntity> Plugins => Set<PluginEntity>();
|
||||
public DbSet<PluginFeatureEntity> PluginFeatures => Set<PluginFeatureEntity>();
|
||||
public DbSet<PluginSettingEntity> PluginSettings => Set<PluginSettingEntity>();
|
||||
public DbSet<ProfileCategoryEntity> ProfileCategories => Set<ProfileCategoryEntity>();
|
||||
public DbSet<ProfileContainerEntity> ProfileContainers => Set<ProfileContainerEntity>();
|
||||
public DbSet<ReleaseEntity> Releases => Set<ReleaseEntity>();
|
||||
|
||||
public string DataFolder { get; set; } = string.Empty;
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Artemis.Storage.Entities.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the configuration of a plugin, each plugin has one configuration
|
||||
/// </summary>
|
||||
[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<PluginFeatureEntity> 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; }
|
||||
}
|
||||
@ -1,15 +1,20 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Artemis.Storage.Entities.Plugins;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the setting of a plugin, a plugin can have multiple settings
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
@ -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; }
|
||||
|
||||
10
src/Artemis.Storage/Entities/RawProfileContainer.cs
Normal file
10
src/Artemis.Storage/Entities/RawProfileContainer.cs
Normal file
@ -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; }
|
||||
}
|
||||
@ -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<int>();
|
||||
}
|
||||
|
||||
[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<DeviceInputIdentifierEntity> InputIdentifiers { get; set; }
|
||||
|
||||
@ -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<string, object> Metadata { get; set; }
|
||||
public Dictionary<string, object>? Metadata { get; set; }
|
||||
}
|
||||
14
src/Artemis.Storage/Exceptions/ArtemisStorageException.cs
Normal file
14
src/Artemis.Storage/Exceptions/ArtemisStorageException.cs
Normal file
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@ -31,10 +31,16 @@ namespace Artemis.Storage.Migrations
|
||||
|
||||
b.Property<string>("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<bool>("IsEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("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<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("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<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("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<string>("Id")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("BlueScale")
|
||||
@ -163,6 +186,7 @@ namespace Artemis.Storage.Migrations
|
||||
|
||||
b.Property<string>("DeviceProvider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("GreenScale")
|
||||
@ -172,12 +196,15 @@ namespace Artemis.Storage.Migrations
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LayoutParameter")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LayoutType")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LogicalLayout")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("PhysicalLayout")
|
||||
@ -226,7 +253,6 @@ namespace Artemis.Storage.Migrations
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Metadata")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
@ -242,6 +268,9 @@ namespace Artemis.Storage.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("EntryId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Entries");
|
||||
});
|
||||
|
||||
@ -15,8 +15,8 @@ namespace Artemis.Storage.Migrations
|
||||
name: "Devices",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
DeviceProvider = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Id = table.Column<string>(type: "TEXT", maxLength: 512, nullable: false),
|
||||
DeviceProvider = table.Column<string>(type: "TEXT", maxLength: 512, nullable: false),
|
||||
X = table.Column<float>(type: "REAL", nullable: false),
|
||||
Y = table.Column<float>(type: "REAL", nullable: false),
|
||||
Rotation = table.Column<float>(type: "REAL", nullable: false),
|
||||
@ -27,9 +27,9 @@ namespace Artemis.Storage.Migrations
|
||||
BlueScale = table.Column<float>(type: "REAL", nullable: false),
|
||||
IsEnabled = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
PhysicalLayout = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
LogicalLayout = table.Column<string>(type: "TEXT", nullable: true),
|
||||
LayoutType = table.Column<string>(type: "TEXT", nullable: true),
|
||||
LayoutParameter = table.Column<string>(type: "TEXT", nullable: true),
|
||||
LogicalLayout = table.Column<string>(type: "TEXT", maxLength: 32, nullable: true),
|
||||
LayoutType = table.Column<string>(type: "TEXT", maxLength: 64, nullable: true),
|
||||
LayoutParameter = table.Column<string>(type: "TEXT", maxLength: 512, nullable: true),
|
||||
Categories = table.Column<string>(type: "TEXT", nullable: false),
|
||||
InputIdentifiers = table.Column<string>(type: "TEXT", nullable: false),
|
||||
InputMappings = table.Column<string>(type: "TEXT", nullable: false)
|
||||
@ -51,7 +51,7 @@ namespace Artemis.Storage.Migrations
|
||||
ReleaseId = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
ReleaseVersion = table.Column<string>(type: "TEXT", nullable: false),
|
||||
InstalledAt = table.Column<DateTimeOffset>(type: "TEXT", nullable: false),
|
||||
Metadata = table.Column<string>(type: "TEXT", nullable: false)
|
||||
Metadata = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@ -63,6 +63,7 @@ namespace Artemis.Storage.Migrations
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
PluginGuid = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
IsEnabled = table.Column<bool>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
@ -76,7 +77,7 @@ namespace Artemis.Storage.Migrations
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
PluginGuid = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", maxLength: 128, nullable: false),
|
||||
Value = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
@ -89,7 +90,7 @@ namespace Artemis.Storage.Migrations
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", maxLength: 64, nullable: false),
|
||||
IsCollapsed = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
IsSuspended = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
Order = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
@ -104,7 +105,7 @@ namespace Artemis.Storage.Migrations
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
Version = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Version = table.Column<string>(type: "TEXT", maxLength: 64, nullable: false),
|
||||
InstalledAt = table.Column<DateTimeOffset>(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<Guid>(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<Guid>(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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -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");
|
||||
@ -28,10 +28,16 @@ namespace Artemis.Storage.Migrations
|
||||
|
||||
b.Property<string>("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<bool>("IsEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid>("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<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("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<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("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<string>("Id")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("BlueScale")
|
||||
@ -160,6 +183,7 @@ namespace Artemis.Storage.Migrations
|
||||
|
||||
b.Property<string>("DeviceProvider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("GreenScale")
|
||||
@ -169,12 +193,15 @@ namespace Artemis.Storage.Migrations
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LayoutParameter")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LayoutType")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LogicalLayout")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("PhysicalLayout")
|
||||
@ -223,7 +250,6 @@ namespace Artemis.Storage.Migrations
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Metadata")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
@ -239,6 +265,9 @@ namespace Artemis.Storage.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("EntryId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Entries");
|
||||
});
|
||||
|
||||
|
||||
@ -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<ArtemisDbContext> 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<DeviceEntity> 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<DeviceEntity> deviceEntities)
|
||||
{
|
||||
using ArtemisDbContext dbContext = getContext();
|
||||
dbContext.UpdateRange(deviceEntities);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
@ -6,44 +6,44 @@ using Artemis.Storage.Repositories.Interfaces;
|
||||
|
||||
namespace Artemis.Storage.Repositories;
|
||||
|
||||
internal class EntryRepository : IEntryRepository
|
||||
internal class EntryRepository(Func<ArtemisDbContext> 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<EntryEntity> 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();
|
||||
}
|
||||
}
|
||||
@ -9,5 +9,6 @@ public interface IDeviceRepository : IRepository
|
||||
void Remove(DeviceEntity deviceEntity);
|
||||
DeviceEntity? Get(string id);
|
||||
IEnumerable<DeviceEntity> GetAll();
|
||||
void SaveChanges();
|
||||
void Save(DeviceEntity deviceEntity);
|
||||
void SaveRange(IEnumerable<DeviceEntity> deviceEntities);
|
||||
}
|
||||
@ -11,5 +11,5 @@ public interface IEntryRepository : IRepository
|
||||
EntryEntity? Get(Guid id);
|
||||
EntryEntity? GetByEntryId(long entryId);
|
||||
IEnumerable<EntryEntity> GetAll();
|
||||
void SaveChanges();
|
||||
void Save(EntryEntity entryEntity);
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -12,5 +12,6 @@ public interface IProfileCategoryRepository : IRepository
|
||||
List<ProfileCategoryEntity> GetAll();
|
||||
ProfileCategoryEntity? Get(Guid id);
|
||||
bool IsUnique(string name, Guid? id);
|
||||
void SaveChanges();
|
||||
void Save(ProfileCategoryEntity profileCategoryEntity);
|
||||
void SaveRange(List<ProfileCategoryEntity> profileCategoryEntities);
|
||||
}
|
||||
@ -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<ProfileContainerEntity> profileContainerEntities);
|
||||
void MigrateProfiles();
|
||||
void MigrateProfile(JsonObject? configurationJson, JsonObject? profileJson);
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
using Artemis.Storage.Entities.General;
|
||||
|
||||
namespace Artemis.Storage.Repositories.Interfaces;
|
||||
|
||||
public interface IReleaseRepository : IRepository
|
||||
{
|
||||
bool SaveVersionInstallDate(string version);
|
||||
ReleaseEntity? GetPreviousInstalledVersion();
|
||||
}
|
||||
@ -6,44 +6,39 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Artemis.Storage.Repositories;
|
||||
|
||||
internal class PluginRepository : IPluginRepository
|
||||
internal class PluginRepository(Func<ArtemisDbContext> 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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,47 +7,63 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Artemis.Storage.Repositories;
|
||||
|
||||
internal class ProfileCategoryRepository : IProfileCategoryRepository
|
||||
internal class ProfileCategoryRepository(Func<ArtemisDbContext> 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<ProfileCategoryEntity> 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<ProfileCategoryEntity> 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);
|
||||
}
|
||||
}
|
||||
91
src/Artemis.Storage/Repositories/ProfileRepository.cs
Normal file
91
src/Artemis.Storage/Repositories/ProfileRepository.cs
Normal file
@ -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<ArtemisDbContext> getContext, List<IProfileMigration> 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<ProfileContainerEntity> 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<RawProfileContainer> containers = dbContext.Database
|
||||
.SqlQueryRaw<RawProfileContainer>("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<int>())
|
||||
continue;
|
||||
|
||||
profileMigrator.Migrate(configurationJson, profileJson);
|
||||
configurationJson["Version"] = profileMigrator.Version;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,34 +5,24 @@ using Artemis.Storage.Repositories.Interfaces;
|
||||
|
||||
namespace Artemis.Storage.Repositories;
|
||||
|
||||
public class ReleaseRepository : IReleaseRepository
|
||||
public class ReleaseRepository(Func<ArtemisDbContext> 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();
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
|
||||
<ProjectReference Include="..\Artemis.Storage.Legacy\Artemis.Storage.Legacy.csproj" />
|
||||
<ProjectReference Include="..\Artemis.UI\Artemis.UI.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
|
||||
<ProjectReference Include="..\Artemis.Storage.Legacy\Artemis.Storage.Legacy.csproj" />
|
||||
<ProjectReference Include="..\Artemis.UI\Artemis.UI.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -21,6 +21,7 @@
|
||||
<PackageReference Include="Material.Icons.Avalonia" />
|
||||
<PackageReference Include="ReactiveUI" />
|
||||
<PackageReference Include="ReactiveUI.Validation" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
|
||||
<ProjectReference Include="..\Artemis.Storage.Legacy\Artemis.Storage.Legacy.csproj" />
|
||||
<ProjectReference Include="..\Artemis.UI\Artemis.UI.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user