diff --git a/Dat/Dat.csproj b/Dat/Dat.csproj
index eda5c6f7..69ab13f1 100644
--- a/Dat/Dat.csproj
+++ b/Dat/Dat.csproj
@@ -10,6 +10,12 @@
true
+
+
+
+
+
+
diff --git a/DataQuery/DataQuery.csproj b/DataQuery/DataQuery.csproj
index 02017247..ddf9a6e2 100644
--- a/DataQuery/DataQuery.csproj
+++ b/DataQuery/DataQuery.csproj
@@ -2,7 +2,7 @@
Exe
- net9.0
+ net10.0
enable
enable
diff --git a/DataQuery/Program.cs b/DataQuery/Program.cs
index 08d46af5..4ca504cd 100644
--- a/DataQuery/Program.cs
+++ b/DataQuery/Program.cs
@@ -1,190 +1,4 @@
-// See https://aka.ms/new-console-template for more information
-using OpenLoco.Common.Logging;
-using Common.Logging;
-using OpenLoco.Dat.Data;
-using Common.Logging;
-using OpenLoco.Dat.FileParsing;
-using Common.Logging;
-using OpenLoco.Dat.Objects;
-using Common.Logging;
-using OpenLoco.Definitions.Database;
-using Common.Logging;
-using System.Reflection;
-using Common.Logging;
+// DataQuery: legacy one-off research console app. All queries previously here have been
+// removed; use the DatabaseTools project for current dev/query tooling.
-var dir = "Q:\\Games\\Locomotion\\Server\\Objects";
-var logger = new Logger();
-var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
-
-//QueryCostIndices(dir, logger, index);
-//QueryCargoCategories(dir, logger, index);
-//QueryVehicleBodyUnkSprites(dir, logger, index);
-//QueryIndustryHasShadows(dir, logger, index);
-
-Console.WriteLine("done");
-
-Console.ReadLine();
-
-static void QueryIndustryHasShadows(string dir, Logger logger, ObjectIndex index)
-{
- var results = new List<(ObjectIndexEntry Obj, ObjectSource ObjectSource)>();
-
- foreach (var obj in index.Objects.Where(x => x.ObjectType == ObjectType.Industry))
- {
- try
- {
- var o = SawyerStreamReader.LoadFullObjectFromFile(Path.Combine(dir, obj.FileName), logger);
- if (o?.LocoObject != null)
- {
- var struc = (IndustryObject)o.Value.LocoObject.Object;
- var header = o.Value.DatFileInfo.S5Header;
- var source = OriginalObjectFiles.GetFileSource(header.Name, header.Checksum);
-
- if (struc.Flags.HasFlag(IndustryObjectFlags.HasShadows))
- {
- results.Add((obj, source));
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"{obj.FileName} - {ex.Message}");
- }
- }
-
- Console.WriteLine(results.Count);
-
- const string csvHeader = "DatName, ObjectSource";
- var lines = results
- .OrderBy(x => x.Obj.DisplayName)
- .Select(x => string.Join(',', x.Obj.DisplayName, x.ObjectSource));
-
- File.WriteAllLines("vehicleBodiesWithUnkSpritesFlag.csv", [csvHeader, .. lines]);
-}
-
-static void QueryVehicleBodyUnkSprites(string dir, Logger logger, ObjectIndex index)
-{
- var results = new List<(ObjectIndexEntry Obj, ObjectSource ObjectSource)>();
-
- foreach (var obj in index.Objects.Where(x => x.ObjectType == ObjectType.Vehicle))
- {
- try
- {
- var o = SawyerStreamReader.LoadFullObjectFromFile(Path.Combine(dir, obj.FileName), logger);
- if (o?.LocoObject != null)
- {
- var struc = (VehicleObject)o.Value.LocoObject.Object;
- var header = o.Value.DatFileInfo.S5Header;
- var source = OriginalObjectFiles.GetFileSource(header.Name, header.Checksum);
-
- if (struc.Flags.HasFlag(VehicleObjectFlags.AlternatingCarSprite))
- {
- results.Add((obj, source));
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"{obj.FileName} - {ex.Message}");
- }
- }
-
- Console.WriteLine(results.Count);
-
- const string csvHeader = "DatName, ObjectSource";
- var lines = results
- .OrderBy(x => x.Obj.DisplayName)
- .Select(x => string.Join(',', x.Obj.DisplayName, x.ObjectSource));
-
- File.WriteAllLines("vehicleBodiesWithUnkSpritesFlag.csv", [csvHeader, .. lines]);
-}
-
-static void QueryCargoCategories(string dir, Logger logger, ObjectIndex index)
-{
- var results = new List<(ObjectIndexEntry Obj, CargoCategory CargoCategory, string LocalisedName, ObjectSource ObjectSource)>();
-
- foreach (var obj in index.Objects.Where(x => x.ObjectType == ObjectType.Cargo))
- {
- try
- {
- var o = SawyerStreamReader.LoadFullObjectFromFile(Path.Combine(dir, obj.FileName), logger);
- if (o?.LocoObject != null)
- {
- var struc = (CargoObject)o.Value.LocoObject.Object;
-
- var header = o.Value.DatFileInfo.S5Header;
- var source = OriginalObjectFiles.GetFileSource(header.Name, header.Checksum);
-
- results.Add((obj, struc.CargoCategory, o.Value.LocoObject.StringTable.Table["Name"][LanguageId.English_UK], source));
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"{obj.FileName} - {ex.Message}");
- }
- }
-
- Console.WriteLine("writing to file");
-
- const string csvHeader = "DatName, CargoCategory, LocalisedName, ObjectSource";
- var lines = results
- .OrderBy(x => x.Obj.DisplayName)
- .Select(x => string.Join(',', x.Obj.DisplayName, (int)x.CargoCategory, x.LocalisedName, x.ObjectSource));
- File.WriteAllLines("cargoCategories.csv", [csvHeader, .. lines]);
-}
-
-static void QueryCostIndices(string dir, Logger logger, ObjectIndex index)
-{
- var results = new List<(ObjectIndexEntry Obj, byte CostIndex, short? RunCostIndex)>();
-
- foreach (var obj in index.Objects)
- {
- try
- {
- var o = SawyerStreamReader.LoadFullObjectFromFile(Path.Combine(dir, obj.FileName), logger);
- if (o?.LocoObject != null)
- {
- var struc = o.Value.LocoObject.Object;
- var type = struc.GetType();
-
- var costIndexProperty = type.GetProperty("CostIndex", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
- var paymentIndexProperty = type.GetProperty("PaymentIndex", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
- var runCostIndexProperty = type.GetProperty("RunCostIndex", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
-
- byte? costIndex = null;
- byte? runCostIndex = null;
-
- if (costIndexProperty?.PropertyType == typeof(byte) && costIndexProperty.GetValue(struc) is byte costIndexValue)
- {
- costIndex = costIndexValue;
- }
- else if (paymentIndexProperty?.PropertyType == typeof(byte) && paymentIndexProperty.GetValue(struc) is byte paymentIndexValue)
- {
- costIndex = paymentIndexValue;
- }
-
- if (runCostIndexProperty?.PropertyType == typeof(byte) && runCostIndexProperty.GetValue(struc) is byte runCostIndexValue)
- {
- runCostIndex = runCostIndexValue;
- }
-
- if (costIndex != null)
- {
- results.Add((obj, costIndex.Value, runCostIndex));
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"{obj.FileName} - {ex.Message}");
- }
- }
-
- Console.WriteLine("writing to file");
-
- const string header = "DatName, ObjectType, CostIndex, RunCostIndex";
- var lines = results
- .OrderBy(x => x.Obj.DisplayName)
- .Select(x => string.Join(',', x.Obj.DisplayName, x.Obj.ObjectType, x.CostIndex, x.RunCostIndex));
- File.WriteAllLines("costIndex.csv", [header, .. lines]);
-}
+Console.WriteLine("DataQuery: no-op. See DatabaseTools for current dev/query tooling.");
diff --git a/DatabaseTools/DatabaseTools.csproj b/DatabaseTools/DatabaseTools.csproj
index 615d9b53..de2c7677 100644
--- a/DatabaseTools/DatabaseTools.csproj
+++ b/DatabaseTools/DatabaseTools.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/DatabaseTools/Services/DatabaseExportService.cs b/DatabaseTools/Services/DatabaseExportService.cs
index 39a45995..f9f37689 100644
--- a/DatabaseTools/Services/DatabaseExportService.cs
+++ b/DatabaseTools/Services/DatabaseExportService.cs
@@ -11,7 +11,7 @@ public static class DatabaseExportService
public static Task ExportAllAsync(ToolsSettings settings, Action log)
=> Task.Run(() =>
{
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
log("Loading from database...");
diff --git a/DatabaseTools/Services/DatabaseHelperScripts.cs b/DatabaseTools/Services/DatabaseHelperScripts.cs
index cade92d4..a362648d 100644
--- a/DatabaseTools/Services/DatabaseHelperScripts.cs
+++ b/DatabaseTools/Services/DatabaseHelperScripts.cs
@@ -48,7 +48,7 @@
using Definitions.ObjectModels.Objects.Wall;
using Definitions.ObjectModels.Objects.Water;
using Definitions.ObjectModels.Types;
-using Index;
+using Definitions;
using Microsoft.EntityFrameworkCore;
using System.IO.Hashing;
using System.Reflection;
@@ -103,7 +103,8 @@ public static Task QueryBuildingVar_AC(ToolsSettings settings, Action lo
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, int var_ac)>();
@@ -143,7 +144,8 @@ public static Task QueryBuildingProducedQuantity(ToolsSettings settings, Action<
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, (string ProducedName, int ProducedQuantity))>();
@@ -179,7 +181,8 @@ public static Task QueryHeadquarters(ToolsSettings settings, Action log)
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, ObjectSource ObjectSource)>();
@@ -216,7 +219,8 @@ public static Task QueryCostIndex(ToolsSettings settings, Action log) =>
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, ObjectSource ObjectSource, ObjectType ObjectType, byte CostIndex)>();
@@ -267,7 +271,8 @@ public static Task QueryTrackStationOneSidedTrack(ToolsSettings settings, Action
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, ObjectSource ObjectSource, List Flags)>();
@@ -323,7 +328,8 @@ public static Task QueryIndustryHasShadows(ToolsSettings settings, Action();
@@ -361,7 +367,8 @@ public static Task QueryVehicleBodyUnkSprites(ToolsSettings settings, Action();
@@ -399,7 +406,8 @@ public static Task QueryCargoCategories(ToolsSettings settings, Action l
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, CargoCategory CargoCategory, string LocalisedName, ObjectSource ObjectSource)>();
@@ -433,7 +441,8 @@ public static Task QueryCostIndices(ToolsSettings settings, Action log)
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var results = new List<(ObjectIndexEntry Obj, byte CostIndex, short? RunCostIndex)>();
@@ -488,11 +497,12 @@ public static Task QueryCostIndices(ToolsSettings settings, Action log)
public static async Task WritexxHash3(ToolsSettings settings, Action log)
{
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var objects = await db.DatObjects.Include(x => x.Object).ToListAsync();
@@ -518,11 +528,12 @@ public static async Task WritexxHash3(ToolsSettings settings, Action log
public static async Task FixObjectDescriptions(ToolsSettings settings, Action log)
{
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var objects = await db.Objects.Include(x => x.DatObjects).ToListAsync();
@@ -561,11 +572,12 @@ public static async Task FixObjectDescriptions(ToolsSettings settings, Action log)
{
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
var objects = await db.Objects
.Include(x => x.DatObjects)
@@ -622,8 +634,9 @@ public static async Task SetupSubObjects(ToolsSettings settings, Action
{
var dir = settings.ObjectDirectory;
var logger = new Logger();
- var index = ObjectIndex.LoadOrCreateIndex(dir, logger);
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var indexDb = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile);
+ var index = ObjectIndex.FromDb(indexDb);
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
var objects = await db.Objects.Include(x => x.DatObjects).ToListAsync();
@@ -672,7 +685,7 @@ public static async Task SetupSubObjects(ToolsSettings settings, Action
public static async Task QuerySubObjects(ToolsSettings settings, Action log)
{
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
var results = await db.ObjClimate
diff --git a/DatabaseTools/Services/DatabaseImportService.cs b/DatabaseTools/Services/DatabaseImportService.cs
index b7a79e37..49f56058 100644
--- a/DatabaseTools/Services/DatabaseImportService.cs
+++ b/DatabaseTools/Services/DatabaseImportService.cs
@@ -5,8 +5,8 @@
using Definitions.Database;
using Definitions.ObjectModels.Types;
using Definitions.SourceData;
-using Index;
using Microsoft.EntityFrameworkCore;
+using ObjectService.Services;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -17,7 +17,7 @@ public static class DatabaseImportService
public static Task SeedAllAsync(ToolsSettings settings, Action log)
=> Task.Run(() =>
{
- using var db = LocoDbContext.GetDbFromFile(settings.DatabaseFile)
+ using var db = BaseLocoDbContext.GetDbFromFile(settings.DatabaseFile)
?? throw new InvalidOperationException($"Database not found at {settings.DatabaseFile}");
log($"Database: {settings.DatabaseFile}");
@@ -143,20 +143,20 @@ public static Task SeedAllAsync(ToolsSettings settings, Action log)
if (!db.Objects.Any() && File.Exists(objectMetadataJson) && Directory.Exists(settings.ObjectDirectory))
{
log("Seeding Objects");
- var index = ObjectIndex.LoadOrCreateIndex(settings.ObjectDirectory, logger);
+ var scan = DatFolderScanner.ScanDirectory(settings.ObjectDirectory, logger);
var objectMetadata = JsonSerializer.Deserialize>(File.ReadAllText(objectMetadataJson), jsonOptions);
var objectMetadataDict = objectMetadata!.ToDictionary(x => x.InternalName, x => x);
var gameReleaseDate = new DateOnly(2004, 09, 07);
- foreach (var objIndex in index!.Objects.DistinctBy(x => (x.DisplayName, x.DatChecksum)))
+ foreach (var objIndex in scan.Succeeded.DistinctBy(x => (x.DatName, x.DatChecksum)))
{
- if (!objectMetadataDict.TryGetValue(objIndex.DisplayName, out var meta))
+ if (!objectMetadataDict.TryGetValue(objIndex.DatName, out var meta))
{
meta = new ObjectMetadata(Guid.NewGuid().ToString(), null, [], [], [], null, ObjectAvailability.Available, DateOnly.UtcToday, null, DateOnly.UtcToday, ObjectSource.Custom);
- objectMetadataDict.Add(objIndex.DisplayName, meta);
+ objectMetadataDict.Add(objIndex.DatName, meta);
}
- var filename = Path.Combine(settings.ObjectDirectory, objIndex.FileName);
+ var filename = objIndex.FullPath;
var creationTime = objIndex.ObjectSource is ObjectSource.LocomotionSteam or ObjectSource.LocomotionGoG
? gameReleaseDate
: DateOnly.FromDateTime(File.GetLastWriteTimeUtc(filename));
@@ -186,9 +186,10 @@ public static Task SeedAllAsync(ToolsSettings settings, Action log)
var addedObj = db.Add(tblLocoObject);
var locoLookupTbl = new TblDatObject
{
- DatName = objIndex.DisplayName,
- DatChecksum = objIndex.DatChecksum.Value,
- xxHash3 = objIndex.xxHash3.Value,
+ DatName = objIndex.DatName,
+ DatChecksum = objIndex.DatChecksum,
+ xxHash3 = objIndex.xxHash3,
+ FileName = objIndex.RelativePath,
ObjectId = addedObj.Entity.Id,
Object = tblLocoObject,
};
diff --git a/DatabaseTools/ToolsSettings.cs b/DatabaseTools/ToolsSettings.cs
index 019cbbe1..d0e7eedb 100644
--- a/DatabaseTools/ToolsSettings.cs
+++ b/DatabaseTools/ToolsSettings.cs
@@ -8,7 +8,7 @@ namespace DatabaseTools;
public class ToolsSettings : ReactiveObject
{
- [Reactive] public string DatabaseFile { get; set; } = LocoDbContext.DefaultDb;
+ [Reactive] public string DatabaseFile { get; set; } = BaseLocoDbContext.DefaultDb;
[Reactive] public string ObjectDirectory { get; set; } = "Q:\\Games\\Locomotion\\Server\\Objects";
diff --git a/Definitions/DTO/DtoIndexFolderRequest.cs b/Definitions/DTO/DtoIndexFolderRequest.cs
new file mode 100644
index 00000000..f8dca7b5
--- /dev/null
+++ b/Definitions/DTO/DtoIndexFolderRequest.cs
@@ -0,0 +1,3 @@
+namespace Definitions.DTO;
+
+public record DtoIndexFolderRequest(string Path);
diff --git a/Definitions/DTO/DtoIndexFolderResponse.cs b/Definitions/DTO/DtoIndexFolderResponse.cs
new file mode 100644
index 00000000..20009793
--- /dev/null
+++ b/Definitions/DTO/DtoIndexFolderResponse.cs
@@ -0,0 +1,8 @@
+namespace Definitions.DTO;
+
+public record DtoIndexFolderResponse(
+ string Path,
+ int ScannedCount,
+ int AddedCount,
+ int SkippedCount,
+ int FailedCount);
diff --git a/Definitions/Database/ClientLocoDbContext.cs b/Definitions/Database/ClientLocoDbContext.cs
new file mode 100644
index 00000000..5ee8e797
--- /dev/null
+++ b/Definitions/Database/ClientLocoDbContext.cs
@@ -0,0 +1,15 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Definitions.Database;
+
+// Client-side projection of the Loco object schema. Used by the GUI's embedded
+// ObjectService host so client databases never get ASP.NET Identity tables.
+// No extra members today - reserved as the hook point for any future client-only schema.
+public class ClientLocoDbContext : BaseLocoDbContext
+{
+ public ClientLocoDbContext()
+ { }
+
+ public ClientLocoDbContext(DbContextOptions options) : base(options)
+ { }
+}
diff --git a/Definitions/Database/DataTables/TblDatObject.cs b/Definitions/Database/DataTables/TblDatObject.cs
index 6f4711e6..34537319 100644
--- a/Definitions/Database/DataTables/TblDatObject.cs
+++ b/Definitions/Database/DataTables/TblDatObject.cs
@@ -12,6 +12,11 @@ public class TblDatObject : DbIdObject
public required ulong xxHash3 { get; set; } // technically a byte[], but we'll use 64-bit int for faster comparison
+ // Optional path to the .dat file on disk. Used by the local (client-side) index
+ // to track where each DAT lives in the user's folder. Server stores either the
+ // relative path under ObjectsCustomFolder or leaves this null.
+ public string? FileName { get; set; }
+
public required UniqueObjectId ObjectId { get; set; } // FK property
public TblObject Object { get; set; } = null!; // navigation property. a DAT object must ALWAYS reference an OL object
diff --git a/Definitions/Database/Identity/TblUser.cs b/Definitions/Database/Identity/TblUser.cs
index 13cf22f9..7832c04c 100644
--- a/Definitions/Database/Identity/TblUser.cs
+++ b/Definitions/Database/Identity/TblUser.cs
@@ -4,6 +4,8 @@ namespace Definitions.Database;
public class TblUser : IdentityUser, IHasId
{
+ // FK only - the navigation property is intentionally omitted because TblAuthor lives in
+ // LocoDbContext while TblUser lives in IdentityContext. Cross-context navigations are
+ // not supported; consumers should resolve the author via LocoDbContext.Authors.Find(...).
public UniqueObjectId? AssociatedAuthorId { get; set; }
- public TblAuthor? AssociatedAuthor { get; set; }
}
diff --git a/Definitions/Database/IdentityContext.cs b/Definitions/Database/IdentityContext.cs
new file mode 100644
index 00000000..ac77d009
--- /dev/null
+++ b/Definitions/Database/IdentityContext.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+
+namespace Definitions.Database;
+
+// Holds the ASP.NET Core Identity schema only. Shares the same SQLite file as LocoDbContext
+// but tracks migrations in a separate __EFMigrationsHistory_Identity table.
+//
+// This context is server-only. Clients running purely against LocoDbContext will not have
+// Identity tables in their local DB and will not register this context with DI.
+public class IdentityContext : IdentityDbContext
+{
+ public const string MigrationsHistoryTableName = "__EFMigrationsHistory_Identity";
+
+ public IdentityContext()
+ { }
+
+ public IdentityContext(DbContextOptions options) : base(options)
+ { }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder builder)
+ {
+ if (!builder.IsConfigured)
+ {
+ // Default to the same SQLite file used by LocoDbContext for the design-time/CLI case
+ _ = builder.UseSqlite(
+ $"Data Source={BaseLocoDbContext.DefaultDb}",
+ sql => sql.MigrationsHistoryTable(MigrationsHistoryTableName));
+ }
+ }
+}
diff --git a/Definitions/Database/LocoDbContext.cs b/Definitions/Database/LocoDbContext.cs
index 3d453d51..46a67cd9 100644
--- a/Definitions/Database/LocoDbContext.cs
+++ b/Definitions/Database/LocoDbContext.cs
@@ -1,9 +1,12 @@
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Definitions.Database;
-public class LocoDbContext : IdentityDbContext
+// Holds the object-domain schema shared by both the server-side and client-side hosting
+// modes. Identity tables live in IdentityContext (server-only) and are not part of this
+// hierarchy. Use ClientLocoDbContext or ServerLocoDbContext to materialise a concrete
+// context; this base class only carries the schema definition.
+public abstract class BaseLocoDbContext : DbContext
{
#region ReferenceData
@@ -102,13 +105,13 @@ public class LocoDbContext : IdentityDbContext options) : base(options)
+ protected BaseLocoDbContext()
{ }
- public const string DefaultDb = "Q:\\Games\\Locomotion\\Database\\loco-test.db";
+ protected BaseLocoDbContext(DbContextOptions options) : base(options)
+ { }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
@@ -130,18 +133,26 @@ protected override void OnConfiguring(DbContextOptionsBuilder builder)
return null;
}
- protected override void OnModelCreating(ModelBuilder modelBuilder)
+
+ public bool DoesObjectExist(string datName, uint datChecksum, out TblObject? existingObject)
{
- base.OnModelCreating(modelBuilder);
+ // there's a unique constraint on the composite key index (DatName, DatChecksum), so check existence first so no exceptions
+ // this isn't necessary since we're already filtering in LINQ, but if we were adding to a non-empty database, this would be necessary
+ var existingEntityInDb = DatObjects
+ .SingleOrDefault(e => e.DatName == datName && e.DatChecksum == datChecksum)?.Object;
- //_ = modelBuilder.Entity()
- // .HasAlternateKey(o => new { o.SubObjectId, o.ObjectType });
+ var existingEntityInChangeTracker = ChangeTracker.Entries()
+ .Where(e => e.State == EntityState.Added && e.Entity.GetType() == typeof(TblDatObject))
+ .Select(e => e.Entity as TblDatObject)
+ .SingleOrDefault(e => e!.DatName == datName && e.DatChecksum == datChecksum)?.Object;
- // Configure the one-to-many relationship
- //modelBuilder.Entity()
- // .HasOne(oi => oi.Order) // OrderItem has one Order
- // .WithMany(o => o.OrderItems) // Order has many OrderItems
- // .HasForeignKey(oi => new { oi.OrderNumber, oi.CustomerCode }); // The composite foreign key on OrderItem
+ existingObject = existingEntityInDb ?? existingEntityInChangeTracker;
+ return existingObject != null;
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
_ = modelBuilder.Entity()
.Property(b => b.UploadedDate)
@@ -156,20 +167,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.Property(b => b.UploadedDate)
.HasDefaultValueSql("date('now')"); // this is necessary, it seems like a bug in sqlite
}
+}
- public bool DoesObjectExist(string datName, uint datChecksum, out TblObject? existingObject)
- {
- // there's a unique constraint on the composite key index (DatName, DatChecksum), so check existence first so no exceptions
- // this isn't necessary since we're already filtering in LINQ, but if we were adding to a non-empty database, this would be necessary
- var existingEntityInDb = DatObjects
- .SingleOrDefault(e => e.DatName == datName && e.DatChecksum == datChecksum)?.Object;
-
- var existingEntityInChangeTracker = ChangeTracker.Entries()
- .Where(e => e.State == EntityState.Added && e.Entity.GetType() == typeof(TblDatObject))
- .Select(e => e.Entity as TblDatObject)
- .SingleOrDefault(e => e!.DatName == datName && e.DatChecksum == datChecksum)?.Object;
+// Existing concrete context. Kept under this name so that the EF migrations snapshot in
+// /Definitions/Migrations/Loco continues to apply without regeneration. Both the standalone
+// server and the existing tests/tools still bind to this type at runtime.
+public class LocoDbContext : BaseLocoDbContext
+{
+ public LocoDbContext()
+ { }
- existingObject = existingEntityInDb ?? existingEntityInChangeTracker;
- return existingObject != null;
- }
+ public LocoDbContext(DbContextOptions options) : base(options)
+ { }
}
diff --git a/Definitions/Database/ServerLocoDbContext.cs b/Definitions/Database/ServerLocoDbContext.cs
new file mode 100644
index 00000000..0f5185d6
--- /dev/null
+++ b/Definitions/Database/ServerLocoDbContext.cs
@@ -0,0 +1,15 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Definitions.Database;
+
+// Server-side projection of the Loco object schema. Identity tables remain in the
+// separate IdentityContext (server-only). No extra members today - reserved as the
+// hook point for any future server-only schema additions (e.g. audit logs, jobs).
+public class ServerLocoDbContext : BaseLocoDbContext
+{
+ public ServerLocoDbContext()
+ { }
+
+ public ServerLocoDbContext(DbContextOptions options) : base(options)
+ { }
+}
diff --git a/Definitions/FileLocation.cs b/Definitions/FileLocation.cs
new file mode 100644
index 00000000..65941b90
--- /dev/null
+++ b/Definitions/FileLocation.cs
@@ -0,0 +1,11 @@
+namespace Definitions;
+
+// Indicates the origin of an object record from the perspective of the editor UI.
+// Local = on the user's disk and tracked by the local SQLite index.
+// Online = retrieved from a remote ObjectService.
+[Flags]
+public enum FileLocation
+{
+ Local,
+ Online,
+}
diff --git a/Definitions/Migrations/20250112060337_InitialCreate.Designer.cs b/Definitions/Migrations/20250112060337_InitialCreate.Designer.cs
deleted file mode 100644
index 1995957b..00000000
--- a/Definitions/Migrations/20250112060337_InitialCreate.Designer.cs
+++ /dev/null
@@ -1,589 +0,0 @@
-//
-using Definitions.Database;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using System;
-
-#nullable disable
-
-namespace Definitions.Database.Migrations;
-
- [DbContext(typeof(LocoDbContext))]
- [Migration("20250112060337_InitialCreate")]
- partial class InitialCreate
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "8.0.10");
-
- modelBuilder.Entity("Definitions.Database.TblAuthor", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.ToTable("Authors");
- });
-
- modelBuilder.Entity("Definitions.Database.TblLicence", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Text")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Licences");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObject", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Availability")
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("DatChecksum")
- .HasColumnType("INTEGER");
-
- b.Property("DatName")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectSource")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectType")
- .HasColumnType("INTEGER");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.Property("VehicleType")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.HasIndex("DatName", "DatChecksum")
- .IsUnique()
- .IsDescending(true, false);
-
- b.ToTable("Objects");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectPack", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("ObjectPacks");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5File", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectSource")
- .HasColumnType("INTEGER");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("SC5Files");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5FilePack", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("SC5FilePacks");
- });
-
- modelBuilder.Entity("Definitions.Database.TblTag", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Tags");
- });
-
- modelBuilder.Entity("TblAuthorTblObject", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "ObjectsId");
-
- b.HasIndex("ObjectsId");
-
- b.ToTable("TblAuthorTblObject");
- });
-
- modelBuilder.Entity("TblAuthorTblObjectPack", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectPacksId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "ObjectPacksId");
-
- b.HasIndex("ObjectPacksId");
-
- b.ToTable("TblAuthorTblObjectPack");
- });
-
- modelBuilder.Entity("TblAuthorTblSC5File", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("SC5FilesId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "SC5FilesId");
-
- b.HasIndex("SC5FilesId");
-
- b.ToTable("TblAuthorTblSC5File");
- });
-
- modelBuilder.Entity("TblAuthorTblSC5FilePack", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("SC5FilePacksId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "SC5FilePacksId");
-
- b.HasIndex("SC5FilePacksId");
-
- b.ToTable("TblAuthorTblSC5FilePack");
- });
-
- modelBuilder.Entity("TblObjectPackTblTag", b =>
- {
- b.Property("ObjectPacksId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("ObjectPacksId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblObjectPackTblTag");
- });
-
- modelBuilder.Entity("TblObjectTblObjectPack", b =>
- {
- b.Property("ObjectPacksId")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("ObjectPacksId", "ObjectsId");
-
- b.HasIndex("ObjectsId");
-
- b.ToTable("TblObjectTblObjectPack");
- });
-
- modelBuilder.Entity("TblObjectTblTag", b =>
- {
- b.Property("ObjectsId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("ObjectsId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblObjectTblTag");
- });
-
- modelBuilder.Entity("TblSC5FilePackTblTag", b =>
- {
- b.Property("SC5FilePacksId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("SC5FilePacksId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblSC5FilePackTblTag");
- });
-
- modelBuilder.Entity("TblSC5FileTblSC5FilePack", b =>
- {
- b.Property("SC5FilePacksId")
- .HasColumnType("INTEGER");
-
- b.Property("SC5FilesId")
- .HasColumnType("INTEGER");
-
- b.HasKey("SC5FilePacksId", "SC5FilesId");
-
- b.HasIndex("SC5FilesId");
-
- b.ToTable("TblSC5FileTblSC5FilePack");
- });
-
- modelBuilder.Entity("TblSC5FileTblTag", b =>
- {
- b.Property("SC5FilesId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("SC5FilesId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblSC5FileTblTag");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObject", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectPack", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5File", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5FilePack", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("TblAuthorTblObject", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblObject", null)
- .WithMany()
- .HasForeignKey("ObjectsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblAuthorTblObjectPack", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblObjectPack", null)
- .WithMany()
- .HasForeignKey("ObjectPacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblAuthorTblSC5File", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblSC5File", null)
- .WithMany()
- .HasForeignKey("SC5FilesId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblAuthorTblSC5FilePack", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblSC5FilePack", null)
- .WithMany()
- .HasForeignKey("SC5FilePacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblObjectPackTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblObjectPack", null)
- .WithMany()
- .HasForeignKey("ObjectPacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblObjectTblObjectPack", b =>
- {
- b.HasOne("Definitions.Database.TblObjectPack", null)
- .WithMany()
- .HasForeignKey("ObjectPacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblObject", null)
- .WithMany()
- .HasForeignKey("ObjectsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblObjectTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblObject", null)
- .WithMany()
- .HasForeignKey("ObjectsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblSC5FilePackTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblSC5FilePack", null)
- .WithMany()
- .HasForeignKey("SC5FilePacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblSC5FileTblSC5FilePack", b =>
- {
- b.HasOne("Definitions.Database.TblSC5FilePack", null)
- .WithMany()
- .HasForeignKey("SC5FilePacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblSC5File", null)
- .WithMany()
- .HasForeignKey("SC5FilesId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblSC5FileTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblSC5File", null)
- .WithMany()
- .HasForeignKey("SC5FilesId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-#pragma warning restore 612, 618
- }
- }
diff --git a/Definitions/Migrations/20250112060337_InitialCreate.cs b/Definitions/Migrations/20250112060337_InitialCreate.cs
deleted file mode 100644
index 8597328f..00000000
--- a/Definitions/Migrations/20250112060337_InitialCreate.cs
+++ /dev/null
@@ -1,560 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace Definitions.Database.Migrations;
-
-///
-public partial class InitialCreate : Migration
-{
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- _ = migrationBuilder.CreateTable(
- name: "Authors",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Name = table.Column(type: "TEXT", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_Authors", x => x.Id);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "Licences",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Name = table.Column(type: "TEXT", nullable: false),
- Text = table.Column(type: "TEXT", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_Licences", x => x.Id);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "Tags",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Name = table.Column(type: "TEXT", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_Tags", x => x.Id);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "ObjectPacks",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Name = table.Column(type: "TEXT", nullable: false),
- Description = table.Column(type: "TEXT", nullable: true),
- LicenceId = table.Column(type: "INTEGER", nullable: true),
- CreatedDate = table.Column(type: "TEXT", nullable: true),
- ModifiedDate = table.Column(type: "TEXT", nullable: true),
- UploadedDate = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime(datetime('now', 'localtime'), 'utc')")
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_ObjectPacks", x => x.Id);
- _ = table.ForeignKey(
- name: "FK_ObjectPacks_Licences_LicenceId",
- column: x => x.LicenceId,
- principalTable: "Licences",
- principalColumn: "Id");
- });
-
- _ = migrationBuilder.CreateTable(
- name: "Objects",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- DatName = table.Column(type: "TEXT", nullable: false),
- DatChecksum = table.Column(type: "INTEGER", nullable: false),
- ObjectSource = table.Column(type: "INTEGER", nullable: false),
- ObjectType = table.Column(type: "INTEGER", nullable: false),
- VehicleType = table.Column(type: "INTEGER", nullable: true),
- Availability = table.Column(type: "INTEGER", nullable: false),
- Name = table.Column(type: "TEXT", nullable: false),
- Description = table.Column(type: "TEXT", nullable: true),
- LicenceId = table.Column(type: "INTEGER", nullable: true),
- CreatedDate = table.Column(type: "TEXT", nullable: true),
- ModifiedDate = table.Column(type: "TEXT", nullable: true),
- UploadedDate = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime(datetime('now', 'localtime'), 'utc')")
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_Objects", x => x.Id);
- _ = table.ForeignKey(
- name: "FK_Objects_Licences_LicenceId",
- column: x => x.LicenceId,
- principalTable: "Licences",
- principalColumn: "Id");
- });
-
- _ = migrationBuilder.CreateTable(
- name: "SC5FilePacks",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Name = table.Column(type: "TEXT", nullable: false),
- Description = table.Column(type: "TEXT", nullable: true),
- LicenceId = table.Column(type: "INTEGER", nullable: true),
- CreatedDate = table.Column(type: "TEXT", nullable: true),
- ModifiedDate = table.Column(type: "TEXT", nullable: true),
- UploadedDate = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime(datetime('now', 'localtime'), 'utc')")
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_SC5FilePacks", x => x.Id);
- _ = table.ForeignKey(
- name: "FK_SC5FilePacks_Licences_LicenceId",
- column: x => x.LicenceId,
- principalTable: "Licences",
- principalColumn: "Id");
- });
-
- _ = migrationBuilder.CreateTable(
- name: "SC5Files",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- ObjectSource = table.Column(type: "INTEGER", nullable: false),
- Name = table.Column(type: "TEXT", nullable: false),
- Description = table.Column(type: "TEXT", nullable: true),
- LicenceId = table.Column(type: "INTEGER", nullable: true),
- CreatedDate = table.Column(type: "TEXT", nullable: true),
- ModifiedDate = table.Column(type: "TEXT", nullable: true),
- UploadedDate = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime(datetime('now', 'localtime'), 'utc')")
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_SC5Files", x => x.Id);
- _ = table.ForeignKey(
- name: "FK_SC5Files_Licences_LicenceId",
- column: x => x.LicenceId,
- principalTable: "Licences",
- principalColumn: "Id");
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblAuthorTblObjectPack",
- columns: table => new
- {
- AuthorsId = table.Column(type: "INTEGER", nullable: false),
- ObjectPacksId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblAuthorTblObjectPack", x => new { x.AuthorsId, x.ObjectPacksId });
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblObjectPack_Authors_AuthorsId",
- column: x => x.AuthorsId,
- principalTable: "Authors",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblObjectPack_ObjectPacks_ObjectPacksId",
- column: x => x.ObjectPacksId,
- principalTable: "ObjectPacks",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblObjectPackTblTag",
- columns: table => new
- {
- ObjectPacksId = table.Column(type: "INTEGER", nullable: false),
- TagsId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblObjectPackTblTag", x => new { x.ObjectPacksId, x.TagsId });
- _ = table.ForeignKey(
- name: "FK_TblObjectPackTblTag_ObjectPacks_ObjectPacksId",
- column: x => x.ObjectPacksId,
- principalTable: "ObjectPacks",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblObjectPackTblTag_Tags_TagsId",
- column: x => x.TagsId,
- principalTable: "Tags",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblAuthorTblObject",
- columns: table => new
- {
- AuthorsId = table.Column(type: "INTEGER", nullable: false),
- ObjectsId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblAuthorTblObject", x => new { x.AuthorsId, x.ObjectsId });
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblObject_Authors_AuthorsId",
- column: x => x.AuthorsId,
- principalTable: "Authors",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblObject_Objects_ObjectsId",
- column: x => x.ObjectsId,
- principalTable: "Objects",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblObjectTblObjectPack",
- columns: table => new
- {
- ObjectPacksId = table.Column(type: "INTEGER", nullable: false),
- ObjectsId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblObjectTblObjectPack", x => new { x.ObjectPacksId, x.ObjectsId });
- _ = table.ForeignKey(
- name: "FK_TblObjectTblObjectPack_ObjectPacks_ObjectPacksId",
- column: x => x.ObjectPacksId,
- principalTable: "ObjectPacks",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblObjectTblObjectPack_Objects_ObjectsId",
- column: x => x.ObjectsId,
- principalTable: "Objects",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblObjectTblTag",
- columns: table => new
- {
- ObjectsId = table.Column(type: "INTEGER", nullable: false),
- TagsId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblObjectTblTag", x => new { x.ObjectsId, x.TagsId });
- _ = table.ForeignKey(
- name: "FK_TblObjectTblTag_Objects_ObjectsId",
- column: x => x.ObjectsId,
- principalTable: "Objects",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblObjectTblTag_Tags_TagsId",
- column: x => x.TagsId,
- principalTable: "Tags",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblAuthorTblSC5FilePack",
- columns: table => new
- {
- AuthorsId = table.Column(type: "INTEGER", nullable: false),
- SC5FilePacksId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblAuthorTblSC5FilePack", x => new { x.AuthorsId, x.SC5FilePacksId });
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblSC5FilePack_Authors_AuthorsId",
- column: x => x.AuthorsId,
- principalTable: "Authors",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblSC5FilePack_SC5FilePacks_SC5FilePacksId",
- column: x => x.SC5FilePacksId,
- principalTable: "SC5FilePacks",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblSC5FilePackTblTag",
- columns: table => new
- {
- SC5FilePacksId = table.Column(type: "INTEGER", nullable: false),
- TagsId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblSC5FilePackTblTag", x => new { x.SC5FilePacksId, x.TagsId });
- _ = table.ForeignKey(
- name: "FK_TblSC5FilePackTblTag_SC5FilePacks_SC5FilePacksId",
- column: x => x.SC5FilePacksId,
- principalTable: "SC5FilePacks",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblSC5FilePackTblTag_Tags_TagsId",
- column: x => x.TagsId,
- principalTable: "Tags",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblAuthorTblSC5File",
- columns: table => new
- {
- AuthorsId = table.Column(type: "INTEGER", nullable: false),
- SC5FilesId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblAuthorTblSC5File", x => new { x.AuthorsId, x.SC5FilesId });
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblSC5File_Authors_AuthorsId",
- column: x => x.AuthorsId,
- principalTable: "Authors",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblAuthorTblSC5File_SC5Files_SC5FilesId",
- column: x => x.SC5FilesId,
- principalTable: "SC5Files",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblSC5FileTblSC5FilePack",
- columns: table => new
- {
- SC5FilePacksId = table.Column(type: "INTEGER", nullable: false),
- SC5FilesId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblSC5FileTblSC5FilePack", x => new { x.SC5FilePacksId, x.SC5FilesId });
- _ = table.ForeignKey(
- name: "FK_TblSC5FileTblSC5FilePack_SC5FilePacks_SC5FilePacksId",
- column: x => x.SC5FilePacksId,
- principalTable: "SC5FilePacks",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblSC5FileTblSC5FilePack_SC5Files_SC5FilesId",
- column: x => x.SC5FilesId,
- principalTable: "SC5Files",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateTable(
- name: "TblSC5FileTblTag",
- columns: table => new
- {
- SC5FilesId = table.Column(type: "INTEGER", nullable: false),
- TagsId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_TblSC5FileTblTag", x => new { x.SC5FilesId, x.TagsId });
- _ = table.ForeignKey(
- name: "FK_TblSC5FileTblTag_SC5Files_SC5FilesId",
- column: x => x.SC5FilesId,
- principalTable: "SC5Files",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- _ = table.ForeignKey(
- name: "FK_TblSC5FileTblTag_Tags_TagsId",
- column: x => x.TagsId,
- principalTable: "Tags",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_Licences_Name",
- table: "Licences",
- column: "Name",
- unique: true);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_ObjectPacks_LicenceId",
- table: "ObjectPacks",
- column: "LicenceId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_ObjectPacks_Name",
- table: "ObjectPacks",
- column: "Name",
- unique: true);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_Objects_DatName_DatChecksum",
- table: "Objects",
- columns: ["DatName", "DatChecksum"],
- unique: true,
- descending: [true, false]);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_Objects_LicenceId",
- table: "Objects",
- column: "LicenceId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_Objects_Name",
- table: "Objects",
- column: "Name",
- unique: true);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_SC5FilePacks_LicenceId",
- table: "SC5FilePacks",
- column: "LicenceId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_SC5FilePacks_Name",
- table: "SC5FilePacks",
- column: "Name",
- unique: true);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_SC5Files_LicenceId",
- table: "SC5Files",
- column: "LicenceId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_SC5Files_Name",
- table: "SC5Files",
- column: "Name",
- unique: true);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_Tags_Name",
- table: "Tags",
- column: "Name",
- unique: true);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblAuthorTblObject_ObjectsId",
- table: "TblAuthorTblObject",
- column: "ObjectsId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblAuthorTblObjectPack_ObjectPacksId",
- table: "TblAuthorTblObjectPack",
- column: "ObjectPacksId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblAuthorTblSC5File_SC5FilesId",
- table: "TblAuthorTblSC5File",
- column: "SC5FilesId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblAuthorTblSC5FilePack_SC5FilePacksId",
- table: "TblAuthorTblSC5FilePack",
- column: "SC5FilePacksId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblObjectPackTblTag_TagsId",
- table: "TblObjectPackTblTag",
- column: "TagsId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblObjectTblObjectPack_ObjectsId",
- table: "TblObjectTblObjectPack",
- column: "ObjectsId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblObjectTblTag_TagsId",
- table: "TblObjectTblTag",
- column: "TagsId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblSC5FilePackTblTag_TagsId",
- table: "TblSC5FilePackTblTag",
- column: "TagsId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblSC5FileTblSC5FilePack_SC5FilesId",
- table: "TblSC5FileTblSC5FilePack",
- column: "SC5FilesId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_TblSC5FileTblTag_TagsId",
- table: "TblSC5FileTblTag",
- column: "TagsId");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- _ = migrationBuilder.DropTable(
- name: "TblAuthorTblObject");
-
- _ = migrationBuilder.DropTable(
- name: "TblAuthorTblObjectPack");
-
- _ = migrationBuilder.DropTable(
- name: "TblAuthorTblSC5File");
-
- _ = migrationBuilder.DropTable(
- name: "TblAuthorTblSC5FilePack");
-
- _ = migrationBuilder.DropTable(
- name: "TblObjectPackTblTag");
-
- _ = migrationBuilder.DropTable(
- name: "TblObjectTblObjectPack");
-
- _ = migrationBuilder.DropTable(
- name: "TblObjectTblTag");
-
- _ = migrationBuilder.DropTable(
- name: "TblSC5FilePackTblTag");
-
- _ = migrationBuilder.DropTable(
- name: "TblSC5FileTblSC5FilePack");
-
- _ = migrationBuilder.DropTable(
- name: "TblSC5FileTblTag");
-
- _ = migrationBuilder.DropTable(
- name: "Authors");
-
- _ = migrationBuilder.DropTable(
- name: "ObjectPacks");
-
- _ = migrationBuilder.DropTable(
- name: "Objects");
-
- _ = migrationBuilder.DropTable(
- name: "SC5FilePacks");
-
- _ = migrationBuilder.DropTable(
- name: "SC5Files");
-
- _ = migrationBuilder.DropTable(
- name: "Tags");
-
- _ = migrationBuilder.DropTable(
- name: "Licences");
- }
-}
diff --git a/Definitions/Migrations/20250602004808_AddObjectLookup.Designer.cs b/Definitions/Migrations/20250602004808_AddObjectLookup.Designer.cs
deleted file mode 100644
index 0c357ecc..00000000
--- a/Definitions/Migrations/20250602004808_AddObjectLookup.Designer.cs
+++ /dev/null
@@ -1,630 +0,0 @@
-//
-using Definitions.Database;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using System;
-
-#nullable disable
-
-namespace Definitions.Database.Migrations;
-
- [DbContext(typeof(LocoDbContext))]
- [Migration("20250602004808_AddObjectLookup")]
- partial class AddObjectLookup
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "9.0.3");
-
- modelBuilder.Entity("Definitions.Database.TblAuthor", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.ToTable("Authors");
- });
-
- modelBuilder.Entity("Definitions.Database.TblLicence", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Text")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Licences");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObject", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("DatChecksum")
- .HasColumnType("INTEGER");
-
- b.Property("DatName")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectSource")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectType")
- .HasColumnType("INTEGER");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.Property("VehicleType")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.HasIndex("DatName", "DatChecksum")
- .IsUnique()
- .IsDescending(true, false);
-
- b.ToTable("Objects");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectPack", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("ObjectPacks");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectLookupFromDat", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatChecksum")
- .HasColumnType("INTEGER");
-
- b.Property("DatName")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectId")
- .HasColumnType("INTEGER");
-
- b.Property("xxHash3")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("ObjectId");
-
- b.HasIndex("xxHash3")
- .IsUnique();
-
- b.HasIndex("DatName", "DatChecksum")
- .IsUnique()
- .IsDescending(true, false);
-
- b.ToTable("ObjectDatLookups");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5File", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectSource")
- .HasColumnType("INTEGER");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("SC5Files");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5FilePack", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("SC5FilePacks");
- });
-
- modelBuilder.Entity("Definitions.Database.TblTag", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Tags");
- });
-
- modelBuilder.Entity("TblAuthorTblObject", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "ObjectsId");
-
- b.HasIndex("ObjectsId");
-
- b.ToTable("TblAuthorTblObject");
- });
-
- modelBuilder.Entity("TblAuthorTblObjectPack", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectPacksId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "ObjectPacksId");
-
- b.HasIndex("ObjectPacksId");
-
- b.ToTable("TblAuthorTblObjectPack");
- });
-
- modelBuilder.Entity("TblAuthorTblSC5File", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("SC5FilesId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "SC5FilesId");
-
- b.HasIndex("SC5FilesId");
-
- b.ToTable("TblAuthorTblSC5File");
- });
-
- modelBuilder.Entity("TblAuthorTblSC5FilePack", b =>
- {
- b.Property("AuthorsId")
- .HasColumnType("INTEGER");
-
- b.Property("SC5FilePacksId")
- .HasColumnType("INTEGER");
-
- b.HasKey("AuthorsId", "SC5FilePacksId");
-
- b.HasIndex("SC5FilePacksId");
-
- b.ToTable("TblAuthorTblSC5FilePack");
- });
-
- modelBuilder.Entity("TblObjectPackTblTag", b =>
- {
- b.Property("ObjectPacksId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("ObjectPacksId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblObjectPackTblTag");
- });
-
- modelBuilder.Entity("TblObjectTblObjectPack", b =>
- {
- b.Property("ObjectPacksId")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("ObjectPacksId", "ObjectsId");
-
- b.HasIndex("ObjectsId");
-
- b.ToTable("TblObjectTblObjectPack");
- });
-
- modelBuilder.Entity("TblObjectTblTag", b =>
- {
- b.Property("ObjectsId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("ObjectsId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblObjectTblTag");
- });
-
- modelBuilder.Entity("TblSC5FilePackTblTag", b =>
- {
- b.Property("SC5FilePacksId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("SC5FilePacksId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblSC5FilePackTblTag");
- });
-
- modelBuilder.Entity("TblSC5FileTblSC5FilePack", b =>
- {
- b.Property("SC5FilePacksId")
- .HasColumnType("INTEGER");
-
- b.Property("SC5FilesId")
- .HasColumnType("INTEGER");
-
- b.HasKey("SC5FilePacksId", "SC5FilesId");
-
- b.HasIndex("SC5FilesId");
-
- b.ToTable("TblSC5FileTblSC5FilePack");
- });
-
- modelBuilder.Entity("TblSC5FileTblTag", b =>
- {
- b.Property("SC5FilesId")
- .HasColumnType("INTEGER");
-
- b.Property("TagsId")
- .HasColumnType("INTEGER");
-
- b.HasKey("SC5FilesId", "TagsId");
-
- b.HasIndex("TagsId");
-
- b.ToTable("TblSC5FileTblTag");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObject", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectPack", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectLookupFromDat", b =>
- {
- b.HasOne("Definitions.Database.TblObject", "Object")
- .WithMany()
- .HasForeignKey("ObjectId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Object");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5File", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("Definitions.Database.TblSC5FilePack", b =>
- {
- b.HasOne("Definitions.Database.TblLicence", "Licence")
- .WithMany()
- .HasForeignKey("LicenceId");
-
- b.Navigation("Licence");
- });
-
- modelBuilder.Entity("TblAuthorTblObject", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblObject", null)
- .WithMany()
- .HasForeignKey("ObjectsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblAuthorTblObjectPack", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblObjectPack", null)
- .WithMany()
- .HasForeignKey("ObjectPacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblAuthorTblSC5File", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblSC5File", null)
- .WithMany()
- .HasForeignKey("SC5FilesId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblAuthorTblSC5FilePack", b =>
- {
- b.HasOne("Definitions.Database.TblAuthor", null)
- .WithMany()
- .HasForeignKey("AuthorsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblSC5FilePack", null)
- .WithMany()
- .HasForeignKey("SC5FilePacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblObjectPackTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblObjectPack", null)
- .WithMany()
- .HasForeignKey("ObjectPacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblObjectTblObjectPack", b =>
- {
- b.HasOne("Definitions.Database.TblObjectPack", null)
- .WithMany()
- .HasForeignKey("ObjectPacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblObject", null)
- .WithMany()
- .HasForeignKey("ObjectsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblObjectTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblObject", null)
- .WithMany()
- .HasForeignKey("ObjectsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblSC5FilePackTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblSC5FilePack", null)
- .WithMany()
- .HasForeignKey("SC5FilePacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblSC5FileTblSC5FilePack", b =>
- {
- b.HasOne("Definitions.Database.TblSC5FilePack", null)
- .WithMany()
- .HasForeignKey("SC5FilePacksId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblSC5File", null)
- .WithMany()
- .HasForeignKey("SC5FilesId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-
- modelBuilder.Entity("TblSC5FileTblTag", b =>
- {
- b.HasOne("Definitions.Database.TblSC5File", null)
- .WithMany()
- .HasForeignKey("SC5FilesId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.HasOne("Definitions.Database.TblTag", null)
- .WithMany()
- .HasForeignKey("TagsId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
- });
-#pragma warning restore 612, 618
- }
- }
diff --git a/Definitions/Migrations/20250602004808_AddObjectLookup.cs b/Definitions/Migrations/20250602004808_AddObjectLookup.cs
deleted file mode 100644
index fce00fea..00000000
--- a/Definitions/Migrations/20250602004808_AddObjectLookup.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace Definitions.Database.Migrations;
-
-///
-public partial class AddObjectLookup : Migration
-{
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- _ = migrationBuilder.DropColumn(
- name: "Availability",
- table: "Objects");
-
- _ = migrationBuilder.CreateTable(
- name: "ObjectDatLookups",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- DatName = table.Column(type: "TEXT", nullable: false),
- DatChecksum = table.Column(type: "INTEGER", nullable: false),
- xxHash3 = table.Column(type: "INTEGER", nullable: false),
- ObjectId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- _ = table.PrimaryKey("PK_ObjectDatLookups", x => x.Id);
- _ = table.ForeignKey(
- name: "FK_ObjectDatLookups_Objects_ObjectId",
- column: x => x.ObjectId,
- principalTable: "Objects",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_ObjectDatLookups_DatName_DatChecksum",
- table: "ObjectDatLookups",
- columns: ["DatName", "DatChecksum"],
- unique: true,
- descending: [true, false]);
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_ObjectDatLookups_ObjectId",
- table: "ObjectDatLookups",
- column: "ObjectId");
-
- _ = migrationBuilder.CreateIndex(
- name: "IX_ObjectDatLookups_xxHash3",
- table: "ObjectDatLookups",
- column: "xxHash3",
- unique: true);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- _ = migrationBuilder.DropTable(
- name: "ObjectDatLookups");
-
- _ = migrationBuilder.AddColumn(
- name: "Availability",
- table: "Objects",
- type: "INTEGER",
- nullable: false,
- defaultValue: 0);
- }
-}
diff --git a/Definitions/Migrations/20250603100806_AddStringTable.Designer.cs b/Definitions/Migrations/20250603100806_AddStringTable.Designer.cs
deleted file mode 100644
index 51f34d0c..00000000
--- a/Definitions/Migrations/20250603100806_AddStringTable.Designer.cs
+++ /dev/null
@@ -1,668 +0,0 @@
-//
-using Definitions.Database;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using System;
-
-#nullable disable
-
-namespace Definitions.Database.Migrations;
-
- [DbContext(typeof(LocoDbContext))]
- [Migration("20250603100806_AddStringTable")]
- partial class AddStringTable
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "9.0.5");
-
- modelBuilder.Entity("Definitions.Database.TblAuthor", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Authors");
- });
-
- modelBuilder.Entity("Definitions.Database.TblDatObject", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatChecksum")
- .HasColumnType("INTEGER");
-
- b.Property("DatName")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectId")
- .HasColumnType("INTEGER");
-
- b.Property("xxHash3")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("ObjectId");
-
- b.HasIndex("xxHash3")
- .IsUnique();
-
- b.HasIndex("DatName", "DatChecksum")
- .IsUnique()
- .IsDescending(true, false);
-
- b.ToTable("DatObjects");
- });
-
- modelBuilder.Entity("Definitions.Database.TblLicence", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Text")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Licences");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObject", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("ObjectSource")
- .HasColumnType("INTEGER");
-
- b.Property("ObjectType")
- .HasColumnType("INTEGER");
-
- b.Property("UploadedDate")
- .ValueGeneratedOnAddOrUpdate()
- .HasColumnType("TEXT")
- .HasDefaultValueSql("datetime(datetime('now', 'localtime'), 'utc')");
-
- b.Property("VehicleType")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("LicenceId");
-
- b.HasIndex("Name")
- .IsUnique();
-
- b.ToTable("Objects");
- });
-
- modelBuilder.Entity("Definitions.Database.TblObjectPack", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CreatedDate")
- .HasColumnType("TEXT");
-
- b.Property("Description")
- .HasColumnType("TEXT");
-
- b.Property("LicenceId")
- .HasColumnType("INTEGER");
-
- b.Property("ModifiedDate")
- .HasColumnType("TEXT");
-
- b.Property("Name")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property