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:
@@ -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
File diff suppressed because it is too large
Load Diff
+1033
File diff suppressed because it is too large
Load Diff
+1798
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
File diff suppressed because it is too large
Load Diff
+1086
File diff suppressed because it is too large
Load Diff
+1887
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user