fengling-platform/Fengling.Platform.Infrastructure/PlatformDbContext.cs
movingsam a6558137af feat(03-gateway-infrastructure-update): update Infrastructure layer for GwCluster
- Updated PlatformDbContext: removed GwTenant/GwServiceInstance DbSets, added GwCluster with EF Core config
- Created IClusterStore interface with CRUD and Destination management methods
- Created ClusterStore<TContext> implementation with soft delete and embedded Destinations support
- Deleted obsolete IInstanceStore and InstanceStore (replaced by IClusterStore)
- Updated Extensions.cs and GatewayExtensions.cs to register IClusterStore

Plan 03 of Phase 03 complete.
2026-03-03 15:46:57 +08:00

142 lines
5.9 KiB
C#

using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
using Fengling.Platform.Domain.AggregatesModel.RoleAggregate;
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
using Fengling.Platform.Domain.AggregatesModel.UserAggregate;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Fengling.Platform.Infrastructure;
public class PlatformDbContext(DbContextOptions options)
: IdentityDbContext<ApplicationUser, ApplicationRole, long>(options)
{
public DbSet<Tenant> Tenants => Set<Tenant>();
public DbSet<AccessLog> AccessLogs => Set<AccessLog>();
public DbSet<AuditLog> AuditLogs => Set<AuditLog>();
// Gateway 实体
public DbSet<GwTenantRoute> GwTenantRoutes => Set<GwTenantRoute>();
public DbSet<GwCluster> GwClusters => Set<GwCluster>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
if (modelBuilder is null)
{
throw new ArgumentNullException(nameof(modelBuilder));
}
modelBuilder.Entity<ApplicationUser>(entity =>
{
entity.Property(e => e.PhoneNumber).HasMaxLength(20);
entity.HasIndex(e => e.PhoneNumber).IsUnique();
entity.OwnsOne(e => e.TenantInfo, navigationBuilder =>
{
navigationBuilder.Property(t => t.TenantCode).HasColumnName("TenantCode");
navigationBuilder.Property(t => t.TenantId).HasColumnName("TenantId");
navigationBuilder.Property(t => t.TenantName).HasColumnName("TenantName");
navigationBuilder.WithOwner();
});
});
modelBuilder.Entity<ApplicationRole>(entity =>
{
entity.Property(e => e.Description).HasMaxLength(200);
});
modelBuilder.Entity<AccessLog>(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => e.CreatedAt);
entity.HasIndex(e => e.UserName);
entity.HasIndex(e => e.TenantId);
entity.HasIndex(e => e.Action);
entity.HasIndex(e => e.Status);
entity.Property(e => e.UserName).HasMaxLength(50);
entity.Property(e => e.TenantId).HasMaxLength(50);
entity.Property(e => e.Action).HasMaxLength(20);
entity.Property(e => e.Resource).HasMaxLength(200);
entity.Property(e => e.Method).HasMaxLength(10);
entity.Property(e => e.IpAddress).HasMaxLength(50);
entity.Property(e => e.UserAgent).HasMaxLength(500);
entity.Property(e => e.Status).HasMaxLength(20);
});
modelBuilder.Entity<AuditLog>(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => e.CreatedAt);
entity.HasIndex(e => e.Operator);
entity.HasIndex(e => e.TenantId);
entity.HasIndex(e => e.Operation);
entity.HasIndex(e => e.Action);
entity.Property(e => e.Operator).HasMaxLength(50);
entity.Property(e => e.TenantId).HasMaxLength(50);
entity.Property(e => e.Operation).HasMaxLength(20);
entity.Property(e => e.Action).HasMaxLength(20);
entity.Property(e => e.TargetType).HasMaxLength(50);
entity.Property(e => e.TargetName).HasMaxLength(100);
entity.Property(e => e.IpAddress).HasMaxLength(50);
entity.Property(e => e.Description).HasMaxLength(500);
entity.Property(e => e.Status).HasMaxLength(20);
});
// Gateway 实体配置
modelBuilder.Entity<GwTenantRoute>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.TenantCode).HasMaxLength(50);
entity.Property(e => e.ServiceName).HasMaxLength(100).IsRequired();
entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired();
entity.Property(e => e.PathPattern).HasMaxLength(200).IsRequired();
entity.HasIndex(e => e.TenantCode);
entity.HasIndex(e => e.ServiceName);
entity.HasIndex(e => e.ClusterId);
entity.HasIndex(e => new { e.ServiceName, e.IsGlobal, e.Status });
});
// GwCluster 聚合根配置 - 使用 Owned 类型
modelBuilder.Entity<GwCluster>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.ClusterId).HasMaxLength(100).IsRequired();
entity.Property(e => e.Name).HasMaxLength(100).IsRequired();
entity.Property(e => e.Description).HasMaxLength(500);
entity.Property(e => e.LoadBalancingPolicy).HasMaxLength(50);
entity.HasIndex(e => e.ClusterId).IsUnique();
entity.HasIndex(e => e.Name);
entity.HasIndex(e => e.Status);
// 配置内嵌的目标端点列表 - 使用 OwnedMany
entity.OwnsMany(e => e.Destinations, owned =>
{
owned.WithOwner().HasForeignKey("ClusterId");
owned.Property<string>("ClusterId").HasMaxLength(100);
owned.Property(d => d.DestinationId).HasMaxLength(100).IsRequired();
owned.Property(d => d.Address).HasMaxLength(200).IsRequired();
owned.Property(d => d.Health).HasMaxLength(200);
owned.HasIndex("ClusterId", "DestinationId");
});
// 配置内嵌健康检查配置
entity.OwnsOne(e => e.HealthCheck, owned =>
{
owned.Property(h => h.Path).HasMaxLength(200);
});
// 配置内嵌会话亲和配置
entity.OwnsOne(e => e.SessionAffinity, owned =>
{
owned.Property(s => s.Policy).HasMaxLength(50);
owned.Property(s => s.AffinityKeyName).HasMaxLength(50);
});
});
modelBuilder.ApplyConfigurationsFromAssembly(typeof(PlatformDbContext).Assembly);
base.OnModelCreating(modelBuilder);
}
}