From 81e5718e05625c2bf5c0f8029d44784f30fc4b06 Mon Sep 17 00:00:00 2001 From: rpaciorek Date: Thu, 31 Aug 2023 18:46:03 +0000 Subject: [PATCH] foreign keys for table PairData + DragonId column + DB schema improvements (#30) * DB schema improvements - add column DragonId to table PairData - add foreign keys for table PairData - remove unused column InventoryId from Vikings table - simplifying relations viking -> selected dragon - remove SelectedViking and SelectedVikingId from Dragon - remove column SelectedVikingId from Dragons table - cleanup and arrangement code in DBContext.cs * support for dragons PairData in KeyValueService and in "pairs" API endpoints --- src/Controllers/Common/ContentController.cs | 10 +- src/Model/DBContext.cs | 107 ++++++++++++-------- src/Model/Dragon.cs | 4 +- src/Model/PairData.cs | 8 ++ src/Model/User.cs | 2 +- src/Model/Viking.cs | 6 +- src/Services/KeyValueService.cs | 45 +++++--- 7 files changed, 113 insertions(+), 69 deletions(-) diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 9f67a4a..ed2b550 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -120,7 +120,7 @@ public class ContentController : Controller { return null; // Get the pair - Model.PairData? pair = keyValueService.GetPairData(session.UserId, session.VikingId, pairId); + Model.PairData? pair = keyValueService.GetPairData(session.User, session.Viking, null, pairId); return keyValueService.ModelToSchema(pair); } @@ -136,7 +136,7 @@ public class ContentController : Controller { if (session is null) return Ok(false); - bool result = keyValueService.SetPairData(session.UserId, session.VikingId, pairId, schemaData); + bool result = keyValueService.SetPairData(session.User, session.Viking, null, pairId, schemaData); return Ok(result); } @@ -149,7 +149,7 @@ public class ContentController : Controller { if (session is null) return null; - Model.PairData? pair = keyValueService.GetPairData(userId, null, pairId); + Model.PairData? pair = keyValueService.GetPairData(session.User, session.Viking, userId, pairId); return keyValueService.ModelToSchema(pair); } @@ -165,7 +165,7 @@ public class ContentController : Controller { if (session is null || string.IsNullOrEmpty(userId)) return Ok(false); - bool result = keyValueService.SetPairData(userId, null, pairId, schemaData); + bool result = keyValueService.SetPairData(session.User, session.Viking, userId, pairId, schemaData); return Ok(result); } @@ -1231,7 +1231,7 @@ public class ContentController : Controller { RaisedPetData data = XmlUtil.DeserializeXml(dragon.RaisedPetData); data.RaisedPetID = dragon.Id; data.EntityID = Guid.Parse(dragon.EntityId); - data.IsSelected = dragon.SelectedViking is not null; + data.IsSelected = (dragon.Viking.SelectedDragonId == dragon.Id); return data; } diff --git a/src/Model/DBContext.cs b/src/Model/DBContext.cs index a8bcb05..d716290 100644 --- a/src/Model/DBContext.cs +++ b/src/Model/DBContext.cs @@ -26,6 +26,7 @@ public class DBContext : DbContext { => optionsBuilder.UseSqlite($"Data Source={DbPath}").UseLazyLoadingProxies(); protected override void OnModelCreating(ModelBuilder builder) { + // Sessions builder.Entity().HasOne(s => s.User) .WithMany(e => e.Sessions) .HasForeignKey(e => e.UserId) @@ -36,10 +37,25 @@ public class DBContext : DbContext { .HasForeignKey(e => e.VikingId) .OnDelete(DeleteBehavior.Cascade); + // Users builder.Entity().HasMany(u => u.Sessions) .WithOne(e => e.User); - builder.Entity().HasMany(u => u.Sessions) + builder.Entity().HasMany(u => u.PairData) + .WithOne(e => e.User); + + builder.Entity().HasMany(u => u.Vikings) + .WithOne(e => e.User); + + // Vikings + builder.Entity().HasOne(v => v.User) + .WithMany(e => e.Vikings) + .HasForeignKey(e => e.UserId); + + builder.Entity().HasMany(v => v.Dragons) + .WithOne(e => e.Viking); + + builder.Entity().HasMany(v => v.Sessions) .WithOne(e => e.Viking); builder.Entity().HasMany(v => v.MissionStates) @@ -51,62 +67,53 @@ public class DBContext : DbContext { builder.Entity().HasMany(v => v.AchievementPoints) .WithOne(e => e.Viking); - builder.Entity().HasOne(s => s.User) - .WithMany(e => e.Vikings) - .HasForeignKey(e => e.UserId); + builder.Entity().HasMany(v => v.PairData) + .WithOne(e => e.Viking); builder.Entity().HasOne(v => v.Inventory) - .WithOne(e => e.Viking) - .HasForeignKey(e => e.InventoryId); + .WithOne(e => e.Viking); - builder.Entity().HasMany(u => u.Vikings) - .WithOne(e => e.User); + builder.Entity().HasMany(v => v.Images) + .WithOne(e => e.Viking); - builder.Entity().HasOne(s => s.Viking) + builder.Entity().HasOne(v => v.SelectedDragon) + .WithOne() + .HasForeignKey(e => e.SelectedDragonId); + + // Dragons + builder.Entity().HasOne(d => d.Viking) .WithMany(e => e.Dragons) .HasForeignKey(e => e.VikingId); - builder.Entity().HasMany(u => u.Dragons) - .WithOne(e => e.Viking); - - builder.Entity().HasOne(s => s.SelectedDragon) - .WithOne(e => e.SelectedViking) - .HasForeignKey(e => e.SelectedVikingId); - - builder.Entity().HasOne(s => s.SelectedViking) - .WithOne(e => e.SelectedDragon) - .HasForeignKey(e => e.SelectedDragonId); - - builder.Entity().HasOne(s => s.Viking) - .WithMany(e => e.Images) - .HasForeignKey(e => e.VikingId); - - builder.Entity().HasMany(u => u.Images) - .WithOne(e => e.Viking); - - builder.Entity().HasOne(v => v.Inventory) - .WithOne(e => e.Viking); - - builder.Entity() - .HasKey(e => e.Id); + builder.Entity().HasMany(d => d.PairData) + .WithOne(e => e.Dragon); + // PairData & Pair builder.Entity().HasMany(p => p.Pairs) .WithOne(e => e.PairData); + builder.Entity().HasOne(p => p.Viking) + .WithMany(e => e.PairData) + .HasForeignKey(e => e.VikingId) + .OnDelete(DeleteBehavior.Cascade); + + builder.Entity().HasOne(p => p.User) + .WithMany(e => e.PairData) + .HasForeignKey(e => e.UserId) + .OnDelete(DeleteBehavior.Cascade); + + builder.Entity().HasOne(p => p.Dragon) + .WithMany(e => e.PairData) + .HasForeignKey(e => e.DragonId) + .OnDelete(DeleteBehavior.Cascade); + builder.Entity() .HasOne(p => p.PairData) .WithMany(pd => pd.Pairs) .HasForeignKey(p => p.MasterId) .HasPrincipalKey(e => e.Id); - builder.Entity().HasKey(e => new { e.Id, e.VikingId, e.MissionId }); - - builder.Entity() - .HasOne(t => t.Viking) - .WithMany(); - - builder.Entity().HasKey(e => e.Id); - + // Inventory & InventoryItem builder.Entity() .HasOne(i => i.Viking) .WithOne(e => e.Inventory) @@ -121,10 +128,7 @@ public class DBContext : DbContext { .WithMany(e => e.InventoryItems) .HasForeignKey(e => e.InventoryId); - builder.Entity().HasOne(m => m.Viking) - .WithMany(e => e.MissionStates) - .HasForeignKey(e => e.VikingId); - + // Room & RoomItem builder.Entity().HasOne(r => r.Viking) .WithMany(e => e.Rooms) .HasForeignKey(e => e.VikingId); @@ -136,6 +140,21 @@ public class DBContext : DbContext { .WithMany(r => r.Items) .HasForeignKey(e => e.RoomId); + // Others .. + builder.Entity().HasOne(s => s.Viking) + .WithMany(e => e.Images) + .HasForeignKey(e => e.VikingId); + + builder.Entity().HasKey(e => new { e.Id, e.VikingId, e.MissionId }); + + builder.Entity() + .HasOne(t => t.Viking) + .WithMany(); + + builder.Entity().HasOne(m => m.Viking) + .WithMany(e => e.MissionStates) + .HasForeignKey(e => e.VikingId); + builder.Entity().HasKey(e => new { e.VikingId, e.Type }); builder.Entity() diff --git a/src/Model/Dragon.cs b/src/Model/Dragon.cs index 955da55..7c56658 100644 --- a/src/Model/Dragon.cs +++ b/src/Model/Dragon.cs @@ -14,12 +14,10 @@ public class Dragon { [Required] public string VikingId { get; set; } = null!; - public string? SelectedVikingId { get; set; } - public string? RaisedPetData { get; set; } public int? PetXP { get; set; } public virtual Viking Viking { get; set; } = null!; - public virtual Viking SelectedViking { get; set; } = null!; + public virtual ICollection PairData { get; set; } = null!; } diff --git a/src/Model/PairData.cs b/src/Model/PairData.cs index c5af83d..d95314d 100644 --- a/src/Model/PairData.cs +++ b/src/Model/PairData.cs @@ -17,5 +17,13 @@ public class PairData { public string? VikingId { get; set; } + public int? DragonId { get; set; } + public virtual ICollection Pairs { get; set; } + + public virtual User? User { get; set; } + + public virtual Viking? Viking { get; set; } + + public virtual Dragon? Dragon { get; set; } } diff --git a/src/Model/User.cs b/src/Model/User.cs index 984165a..39c3d34 100644 --- a/src/Model/User.cs +++ b/src/Model/User.cs @@ -15,6 +15,6 @@ public class User { public string Password { get; set; } = null!; public virtual ICollection Sessions { get; set; } = null!; - public virtual ICollection Vikings { get; set; } = null!; + public virtual ICollection PairData { get; set; } = null!; } diff --git a/src/Model/Viking.cs b/src/Model/Viking.cs index aed5ce4..86a1524 100644 --- a/src/Model/Viking.cs +++ b/src/Model/Viking.cs @@ -22,9 +22,7 @@ public class Viking { public virtual ICollection MissionStates { get; set; } = null!; public virtual ICollection Rooms { get; set; } = null!; public virtual ICollection AchievementPoints { get; set; } = null!; - public virtual Dragon? SelectedDragon { get; set; } - - public int InventoryId { get; set; } - + public virtual ICollection PairData { get; set; } = null!; public virtual Inventory Inventory { get; set; } = null!; + public virtual Dragon? SelectedDragon { get; set; } } diff --git a/src/Services/KeyValueService.cs b/src/Services/KeyValueService.cs index 646d5dc..7ed8b82 100644 --- a/src/Services/KeyValueService.cs +++ b/src/Services/KeyValueService.cs @@ -10,27 +10,24 @@ public class KeyValueService { this.ctx = ctx; } - public Model.PairData? GetPairData(string? UserId, string? VikingId, int pairId) { - Model.PairData? pair = null; - if (VikingId != null) - pair = ctx.PairData.FirstOrDefault(e => e.PairId == pairId && e.VikingId == VikingId); - else if (UserId != null) - pair = ctx.PairData.FirstOrDefault(e => e.PairId == pairId && e.UserId == UserId); - - return pair; + public Model.PairData? GetPairData(User? user, Viking? viking, string? userId, int pairId) { + Dragon? dragon = null; + return CheckOwnerAndGetPairData(ref user, ref viking, ref dragon, userId, pairId); } - public bool SetPairData(string? UserId, string? VikingId, int pairId, Schema.PairData schemaData) { + public bool SetPairData(User? user, Viking? viking, string? userId, int pairId, Schema.PairData schemaData) { // Get the pair - Model.PairData? pair = GetPairData(UserId, VikingId, pairId); + Dragon? dragon = null; + Model.PairData? pair = CheckOwnerAndGetPairData(ref user, ref viking, ref dragon, userId, pairId); // Create the pair if it doesn't exist bool exists = true; if (pair is null) { pair = new Model.PairData { PairId = pairId, - UserId = UserId, - VikingId = VikingId, + UserId = user?.Id, + VikingId = viking?.Id, + DragonId = dragon?.Id, Pairs = new List() }; exists = false; @@ -77,4 +74,28 @@ public class KeyValueService { return new Schema.PairData { Pairs = pairs.ToArray() }; } + private Model.PairData? CheckOwnerAndGetPairData(ref User? user, ref Viking? viking, ref Dragon dragon, string? userId, int pairId) { + if (userId != null) { + // find dragon + dragon = viking?.Dragons.FirstOrDefault(e => e.EntityId == userId); + + // if not dragon then try viking -> check ID + if (dragon != null || viking?.Id != userId) viking = null; + + // if not dragon nor viking then try user -> check ID + if (viking != null || user?.Id != userId) user = null; + } + + // NOTE: only one of (dragon, viking, user) can be not null here + + Model.PairData? pair = null; + if (viking != null) + pair = viking.PairData.FirstOrDefault(e => e.PairId == pairId); + else if (user != null) + pair = user.PairData.FirstOrDefault(e => e.PairId == pairId); + else if (dragon != null) + pair = dragon.PairData.FirstOrDefault(e => e.PairId == pairId); + + return pair; + } }