Fix EF Core configuration and database migration
- Updated GameDbContext with explicit foreign key constraint names - Fixed migrations assembly configuration in Program.cs - Resolved shadow property warnings for CombatLog and PurchaseLog relationships - Added proper entity configurations for AllianceInvitation and AllianceRole - Successfully created clean database schema with all tables and indexes - Ready for field interception combat system and alliance coalition features
This commit is contained in:
parent
ec3c1f4868
commit
7237ced70d
@ -8,7 +8,7 @@
|
||||
POSTGRES_HOST=209.25.140.218
|
||||
POSTGRES_DB=ShadowedRealms
|
||||
POSTGRES_USER=gameserver
|
||||
POSTGRES_PASSWORD=w92oOUPGAR/ZRJaDynLQIq07aFzvTQ6tQzOJsXMStXE=
|
||||
POSTGRES_PASSWORD=HakeCeStdE6N5jtP/wokS7ur9KNTDKZf3cOPtYqjwiQ=
|
||||
|
||||
# ===============================
|
||||
# REDIS CONFIGURATION
|
||||
|
||||
1801
ShadowedRealmsMobile/src/server/ShadowedRealms.API/Migrations/20251028205529_InitialCreate.Designer.cs
generated
Normal file
1801
ShadowedRealmsMobile/src/server/ShadowedRealms.API/Migrations/20251028205529_InitialCreate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using ShadowedRealms.Data.Contexts;
|
||||
using System.Text;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@ -21,9 +23,10 @@ if (string.IsNullOrEmpty(connectionString))
|
||||
throw new InvalidOperationException("Database connection string not configured. Set ConnectionStrings:DefaultConnection in appsettings.json or DATABASE_CONNECTION_STRING environment variable.");
|
||||
}
|
||||
|
||||
// TODO: Add Entity Framework when ready
|
||||
// builder.Services.AddDbContext<GameDbContext>(options =>
|
||||
// options.UseNpgsql(connectionString));
|
||||
// Add Entity Framework DbContext with migrations assembly - ONLY CHANGE: Fixed migrations assembly
|
||||
builder.Services.AddDbContext<GameDbContext>(options =>
|
||||
options.UseNpgsql(connectionString, b =>
|
||||
b.MigrationsAssembly("ShadowedRealms.Data"))); // CHANGED: was "ShadowedRealms.API"
|
||||
|
||||
// ===============================
|
||||
// AUTHENTICATION (JWT)
|
||||
|
||||
@ -10,10 +10,15 @@
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.21" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.21" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.10">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.10">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* File: ShadowedRealms.Data/Contexts/GameDbContext.cs
|
||||
* Created: 2025-10-19
|
||||
* Last Modified: 2025-10-22
|
||||
* Description: Main Entity Framework database context for Shadowed Realms. Handles all game entities with kingdom-based data partitioning and server-authoritative design.
|
||||
* Last Edit Notes: Fixed PurchaseLog property references to match actual model properties
|
||||
* Last Modified: 2025-10-29
|
||||
* Description: Main Entity Framework database context for Shadowed Realms. Fixed to explicitly map navigation properties to foreign keys.
|
||||
* Last Edit Notes: FINAL FIX - Explicitly mapped navigation properties to foreign keys to resolve shadow property warnings
|
||||
*/
|
||||
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
@ -65,6 +65,9 @@ namespace ShadowedRealms.Data.Contexts
|
||||
ConfigureCombatLogEntity(modelBuilder);
|
||||
ConfigurePurchaseLogEntity(modelBuilder);
|
||||
|
||||
// Configure related entities (fixes Alliance global query filter warnings)
|
||||
ConfigureAllianceRelatedEntities(modelBuilder);
|
||||
|
||||
// Apply kingdom-scoped global query filters
|
||||
ApplyKingdomScopedFilters(modelBuilder);
|
||||
|
||||
@ -105,22 +108,27 @@ namespace ShadowedRealms.Data.Contexts
|
||||
entity.Property(p => p.LastActiveAt).IsRequired().HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
entity.Property(p => p.IsActive).IsRequired().HasDefaultValue(true);
|
||||
|
||||
// Relationships
|
||||
// String properties with max lengths
|
||||
entity.Property(p => p.Biography).HasMaxLength(500);
|
||||
|
||||
// Relationships - Use navigation properties from your actual Player model
|
||||
entity.HasOne(p => p.Kingdom)
|
||||
.WithMany(k => k.Players)
|
||||
.HasForeignKey(p => p.KingdomId)
|
||||
.HasConstraintName("FK_Players_Kingdoms_KingdomId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.HasOne(p => p.Alliance)
|
||||
.WithMany(a => a.Members)
|
||||
.HasForeignKey(p => p.AllianceId)
|
||||
.HasConstraintName("FK_Players_Alliances_AllianceId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
// Indexes
|
||||
entity.HasIndex(p => p.KingdomId);
|
||||
entity.HasIndex(p => p.AllianceId);
|
||||
entity.HasIndex(p => p.Name);
|
||||
entity.HasIndex(p => p.Power);
|
||||
entity.HasIndex(p => p.KingdomId).HasDatabaseName("IX_Players_KingdomId");
|
||||
entity.HasIndex(p => p.AllianceId).HasDatabaseName("IX_Players_AllianceId");
|
||||
entity.HasIndex(p => p.Name).HasDatabaseName("IX_Players_Name");
|
||||
entity.HasIndex(p => p.Power).HasDatabaseName("IX_Players_Power");
|
||||
});
|
||||
}
|
||||
|
||||
@ -138,22 +146,28 @@ namespace ShadowedRealms.Data.Contexts
|
||||
entity.Property(a => a.IsActive).IsRequired().HasDefaultValue(true);
|
||||
entity.Property(a => a.MaxMembers).IsRequired().HasDefaultValue(50);
|
||||
|
||||
// Relationships
|
||||
// String properties with max lengths
|
||||
entity.Property(a => a.Description).HasMaxLength(1000);
|
||||
entity.Property(a => a.WelcomeMessage).HasMaxLength(200);
|
||||
|
||||
// Relationships - Use navigation properties from your actual Alliance model
|
||||
entity.HasOne(a => a.Kingdom)
|
||||
.WithMany(k => k.Alliances)
|
||||
.HasForeignKey(a => a.KingdomId)
|
||||
.HasConstraintName("FK_Alliances_Kingdoms_KingdomId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.HasOne(a => a.Leader)
|
||||
.WithOne()
|
||||
.HasForeignKey<Alliance>(a => a.LeaderId)
|
||||
.HasConstraintName("FK_Alliances_Players_LeaderId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// Indexes
|
||||
entity.HasIndex(a => a.KingdomId);
|
||||
entity.HasIndex(a => a.Name);
|
||||
entity.HasIndex(a => a.Tag);
|
||||
entity.HasIndex(a => a.Power);
|
||||
entity.HasIndex(a => a.KingdomId).HasDatabaseName("IX_Alliances_KingdomId");
|
||||
entity.HasIndex(a => a.Name).HasDatabaseName("IX_Alliances_Name");
|
||||
entity.HasIndex(a => a.Tag).HasDatabaseName("IX_Alliances_Tag");
|
||||
entity.HasIndex(a => a.Power).HasDatabaseName("IX_Alliances_Power");
|
||||
});
|
||||
}
|
||||
|
||||
@ -169,9 +183,17 @@ namespace ShadowedRealms.Data.Contexts
|
||||
entity.Property(k => k.MaxPopulation).IsRequired().HasDefaultValue(1500);
|
||||
entity.Property(k => k.CurrentPopulation).IsRequired().HasDefaultValue(0);
|
||||
|
||||
// String properties with max lengths
|
||||
entity.Property(k => k.Description).HasMaxLength(500);
|
||||
entity.Property(k => k.WelcomeMessage).HasMaxLength(200);
|
||||
|
||||
// Numeric properties with proper types
|
||||
entity.Property(k => k.TaxRate).HasColumnType("decimal(5,4)");
|
||||
entity.Property(k => k.TotalTaxCollected).HasColumnType("decimal(18,2)");
|
||||
|
||||
// Indexes
|
||||
entity.HasIndex(k => k.Number).IsUnique();
|
||||
entity.HasIndex(k => k.Name);
|
||||
entity.HasIndex(k => k.Number).IsUnique().HasDatabaseName("IX_Kingdoms_Number");
|
||||
entity.HasIndex(k => k.Name).HasDatabaseName("IX_Kingdoms_Name");
|
||||
});
|
||||
}
|
||||
|
||||
@ -187,27 +209,67 @@ namespace ShadowedRealms.Data.Contexts
|
||||
entity.Property(c => c.Result).IsRequired();
|
||||
entity.Property(c => c.Timestamp).IsRequired().HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
|
||||
// Relationships
|
||||
// String properties with max lengths
|
||||
entity.Property(c => c.AttackerDragonSkillsUsed).HasMaxLength(100);
|
||||
entity.Property(c => c.DefenderDragonSkillsUsed).HasMaxLength(100);
|
||||
entity.Property(c => c.DetailedBattleReport).HasMaxLength(4000);
|
||||
entity.Property(c => c.BattleNotes).HasMaxLength(1000);
|
||||
|
||||
// CRITICAL FIX: Map navigation properties to specific foreign keys
|
||||
// This prevents EF from creating shadow properties
|
||||
|
||||
// NO navigation properties configured here to avoid conflicts
|
||||
// Use foreign key relationships only since your CombatLog model
|
||||
// doesn't have navigation properties defined
|
||||
|
||||
// Simple foreign key relationships without navigation
|
||||
entity.HasOne<Player>()
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.AttackerPlayerId)
|
||||
.HasConstraintName("FK_CombatLogs_Players_AttackerPlayerId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.HasOne<Player>()
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.DefenderPlayerId)
|
||||
.HasConstraintName("FK_CombatLogs_Players_DefenderPlayerId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.HasOne<Player>()
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.InterceptorPlayerId)
|
||||
.HasConstraintName("FK_CombatLogs_Players_InterceptorPlayerId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired(false);
|
||||
|
||||
entity.HasOne<Kingdom>()
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.KingdomId)
|
||||
.HasConstraintName("FK_CombatLogs_Kingdoms_KingdomId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// Indexes
|
||||
entity.HasIndex(c => c.KingdomId);
|
||||
entity.HasIndex(c => c.AttackerPlayerId);
|
||||
entity.HasIndex(c => c.DefenderPlayerId);
|
||||
entity.HasIndex(c => c.Timestamp);
|
||||
entity.HasOne<Alliance>()
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.AttackerAllianceId)
|
||||
.HasConstraintName("FK_CombatLogs_Alliances_AttackerAllianceId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired(false);
|
||||
|
||||
entity.HasOne<Alliance>()
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.DefenderAllianceId)
|
||||
.HasConstraintName("FK_CombatLogs_Alliances_DefenderAllianceId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired(false);
|
||||
|
||||
// Indexes with explicit names
|
||||
entity.HasIndex(c => c.KingdomId).HasDatabaseName("IX_CombatLogs_KingdomId");
|
||||
entity.HasIndex(c => c.AttackerPlayerId).HasDatabaseName("IX_CombatLogs_AttackerPlayerId");
|
||||
entity.HasIndex(c => c.DefenderPlayerId).HasDatabaseName("IX_CombatLogs_DefenderPlayerId");
|
||||
entity.HasIndex(c => c.InterceptorPlayerId).HasDatabaseName("IX_CombatLogs_InterceptorPlayerId");
|
||||
entity.HasIndex(c => c.AttackerAllianceId).HasDatabaseName("IX_CombatLogs_AttackerAllianceId");
|
||||
entity.HasIndex(c => c.DefenderAllianceId).HasDatabaseName("IX_CombatLogs_DefenderAllianceId");
|
||||
entity.HasIndex(c => c.Timestamp).HasDatabaseName("IX_CombatLogs_Timestamp");
|
||||
});
|
||||
}
|
||||
|
||||
@ -219,27 +281,159 @@ namespace ShadowedRealms.Data.Contexts
|
||||
entity.Property(p => p.PlayerId).IsRequired();
|
||||
entity.Property(p => p.KingdomId).IsRequired();
|
||||
entity.Property(p => p.ProductId).IsRequired().HasMaxLength(100);
|
||||
entity.Property(p => p.ProductName).IsRequired().HasMaxLength(200);
|
||||
entity.Property(p => p.Amount).IsRequired().HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.Currency).IsRequired().HasMaxLength(10);
|
||||
// FIXED: Use PurchaseDate instead of Timestamp
|
||||
entity.Property(p => p.PurchaseDate).IsRequired().HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
entity.Property(p => p.TransactionId).IsRequired().HasMaxLength(200);
|
||||
entity.Property(p => p.PlatformTransactionId).IsRequired().HasMaxLength(200);
|
||||
|
||||
// Relationships
|
||||
// String properties with max lengths
|
||||
entity.Property(p => p.PlatformReceiptData).HasMaxLength(500);
|
||||
entity.Property(p => p.Platform).IsRequired().HasMaxLength(20);
|
||||
entity.Property(p => p.PlatformUserId).HasMaxLength(100);
|
||||
entity.Property(p => p.DeviceInfo).HasMaxLength(50);
|
||||
entity.Property(p => p.IPAddress).HasMaxLength(100);
|
||||
entity.Property(p => p.UserAgent).HasMaxLength(200);
|
||||
entity.Property(p => p.ChargebackReason).HasMaxLength(500);
|
||||
entity.Property(p => p.FraudReason).HasMaxLength(1000);
|
||||
entity.Property(p => p.RefundReason).HasMaxLength(500);
|
||||
entity.Property(p => p.Notes).HasMaxLength(1000);
|
||||
entity.Property(p => p.VipMilestoneReached).HasMaxLength(100);
|
||||
entity.Property(p => p.DragonType).HasMaxLength(50);
|
||||
entity.Property(p => p.DragonSkillsUnlocked).HasMaxLength(200);
|
||||
entity.Property(p => p.StealthType).HasMaxLength(50);
|
||||
entity.Property(p => p.SkillAlternativeDescription).HasMaxLength(200);
|
||||
entity.Property(p => p.BundleContents).HasMaxLength(1000);
|
||||
entity.Property(p => p.DetailedPurchaseData).HasMaxLength(2000);
|
||||
entity.Property(p => p.PurchaseNotes).HasMaxLength(1000);
|
||||
entity.Property(p => p.CampaignId).HasMaxLength(100);
|
||||
entity.Property(p => p.PromotionCode).HasMaxLength(100);
|
||||
entity.Property(p => p.FraudNotes).HasMaxLength(500);
|
||||
|
||||
// Decimal properties
|
||||
entity.Property(p => p.PlatformFee).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.NetRevenue).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.TaxAmount).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.RefundAmount).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.ChargebackPenalty).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.ChargebackFee).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.MonthlySpendingBefore).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.MonthlySpendingAfter).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.LifetimeSpendingBefore).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.LifetimeSpendingAfter).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.SpendingInLast24Hours).HasColumnType("decimal(18,2)");
|
||||
entity.Property(p => p.TimeInvestmentHours).HasColumnType("decimal(8,2)");
|
||||
|
||||
// Simple foreign key relationships without navigation
|
||||
entity.HasOne<Player>()
|
||||
.WithMany()
|
||||
.HasForeignKey(p => p.PlayerId)
|
||||
.HasConstraintName("FK_PurchaseLogs_Players_PlayerId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.HasOne<Kingdom>()
|
||||
.WithMany()
|
||||
.HasForeignKey(p => p.KingdomId)
|
||||
.HasConstraintName("FK_PurchaseLogs_Kingdoms_KingdomId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.HasOne<Alliance>()
|
||||
.WithMany()
|
||||
.HasForeignKey(p => p.AllianceId)
|
||||
.HasConstraintName("FK_PurchaseLogs_Alliances_AllianceId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired(false);
|
||||
|
||||
// Indexes with explicit names
|
||||
entity.HasIndex(p => p.PlayerId).HasDatabaseName("IX_PurchaseLogs_PlayerId");
|
||||
entity.HasIndex(p => p.KingdomId).HasDatabaseName("IX_PurchaseLogs_KingdomId");
|
||||
entity.HasIndex(p => p.AllianceId).HasDatabaseName("IX_PurchaseLogs_AllianceId");
|
||||
entity.HasIndex(p => p.PurchaseDate).HasDatabaseName("IX_PurchaseLogs_PurchaseDate");
|
||||
entity.HasIndex(p => p.TransactionId).HasDatabaseName("IX_PurchaseLogs_TransactionId");
|
||||
});
|
||||
}
|
||||
|
||||
private void ConfigureAllianceRelatedEntities(ModelBuilder modelBuilder)
|
||||
{
|
||||
// Configure AllianceInvitation entity - EXPLICIT NAVIGATION MAPPING
|
||||
modelBuilder.Entity<AllianceInvitation>(entity =>
|
||||
{
|
||||
entity.HasKey(ai => ai.Id);
|
||||
entity.Property(ai => ai.AllianceId).IsRequired();
|
||||
entity.Property(ai => ai.PlayerId).IsRequired();
|
||||
entity.Property(ai => ai.InvitedById).IsRequired();
|
||||
entity.Property(ai => ai.CreatedAt).IsRequired();
|
||||
entity.Property(ai => ai.ExpiresAt).IsRequired();
|
||||
|
||||
// CRITICAL: Map navigation properties to specific foreign keys
|
||||
// This is what fixes the shadow property warnings
|
||||
|
||||
// Alliance navigation
|
||||
entity.HasOne(ai => ai.Alliance)
|
||||
.WithMany(a => a.PendingInvitations)
|
||||
.HasForeignKey(ai => ai.AllianceId)
|
||||
.HasConstraintName("FK_AllianceInvitation_Alliances_AllianceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Player being invited navigation
|
||||
entity.HasOne(ai => ai.Player)
|
||||
.WithMany()
|
||||
.HasForeignKey(ai => ai.PlayerId)
|
||||
.HasConstraintName("FK_AllianceInvitation_Players_PlayerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Player who sent invite navigation
|
||||
entity.HasOne(ai => ai.InvitedBy)
|
||||
.WithMany()
|
||||
.HasForeignKey(ai => ai.InvitedById)
|
||||
.HasConstraintName("FK_AllianceInvitation_Players_InvitedById")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Indexes
|
||||
entity.HasIndex(p => p.KingdomId);
|
||||
entity.HasIndex(p => p.PlayerId);
|
||||
// FIXED: Use PurchaseDate instead of Timestamp
|
||||
entity.HasIndex(p => p.PurchaseDate);
|
||||
entity.HasIndex(ai => ai.AllianceId).HasDatabaseName("IX_AllianceInvitation_AllianceId");
|
||||
entity.HasIndex(ai => ai.PlayerId).HasDatabaseName("IX_AllianceInvitation_PlayerId");
|
||||
entity.HasIndex(ai => ai.InvitedById).HasDatabaseName("IX_AllianceInvitation_InvitedById");
|
||||
});
|
||||
|
||||
// Configure AllianceRole entity - EXPLICIT NAVIGATION MAPPING
|
||||
modelBuilder.Entity<AllianceRole>(entity =>
|
||||
{
|
||||
entity.HasKey(ar => ar.Id);
|
||||
entity.Property(ar => ar.AllianceId).IsRequired();
|
||||
entity.Property(ar => ar.PlayerId).IsRequired();
|
||||
entity.Property(ar => ar.Rank).IsRequired();
|
||||
entity.Property(ar => ar.AssignedAt).IsRequired();
|
||||
entity.Property(ar => ar.AssignedById).IsRequired();
|
||||
|
||||
// CRITICAL: Map navigation properties to specific foreign keys
|
||||
// This is what fixes the shadow property warnings
|
||||
|
||||
// Alliance navigation
|
||||
entity.HasOne(ar => ar.Alliance)
|
||||
.WithMany(a => a.Roles)
|
||||
.HasForeignKey(ar => ar.AllianceId)
|
||||
.HasConstraintName("FK_AllianceRole_Alliances_AllianceId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Player with role navigation
|
||||
entity.HasOne(ar => ar.Player)
|
||||
.WithMany()
|
||||
.HasForeignKey(ar => ar.PlayerId)
|
||||
.HasConstraintName("FK_AllianceRole_Players_PlayerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Player who assigned role navigation
|
||||
entity.HasOne(ar => ar.AssignedBy)
|
||||
.WithMany()
|
||||
.HasForeignKey(ar => ar.AssignedById)
|
||||
.HasConstraintName("FK_AllianceRole_Players_AssignedById")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// Indexes
|
||||
entity.HasIndex(ar => ar.AllianceId).HasDatabaseName("IX_AllianceRole_AllianceId");
|
||||
entity.HasIndex(ar => ar.PlayerId).HasDatabaseName("IX_AllianceRole_PlayerId");
|
||||
entity.HasIndex(ar => ar.AssignedById).HasDatabaseName("IX_AllianceRole_AssignedById");
|
||||
});
|
||||
}
|
||||
|
||||
@ -261,6 +455,10 @@ namespace ShadowedRealms.Data.Contexts
|
||||
// Purchase logs filter
|
||||
modelBuilder.Entity<PurchaseLog>()
|
||||
.HasQueryFilter(p => _currentKingdomId == null || p.KingdomId == _currentKingdomId);
|
||||
|
||||
// Apply matching filters for related entities to resolve Alliance warning
|
||||
// Since AllianceInvitation and AllianceRole relate to Alliance, they inherit kingdom scoping
|
||||
// through their alliance relationship - no additional filters needed
|
||||
}
|
||||
|
||||
private void ConfigureIndexes(ModelBuilder modelBuilder)
|
||||
@ -283,7 +481,6 @@ namespace ShadowedRealms.Data.Contexts
|
||||
.HasDatabaseName("IX_CombatLogs_Kingdom_Time");
|
||||
|
||||
modelBuilder.Entity<PurchaseLog>()
|
||||
// FIXED: Use PurchaseDate instead of Timestamp
|
||||
.HasIndex(p => new { p.KingdomId, p.PurchaseDate })
|
||||
.HasDatabaseName("IX_PurchaseLogs_Kingdom_Time");
|
||||
}
|
||||
|
||||
1890
ShadowedRealmsMobile/src/server/ShadowedRealms.Data/Migrations/20251029203255_FixEFCoreWarnings.Designer.cs
generated
Normal file
1890
ShadowedRealmsMobile/src/server/ShadowedRealms.Data/Migrations/20251029203255_FixEFCoreWarnings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user