using Microsoft.EntityFrameworkCore;
namespace RobotNet10.MapManager.Data;
///
/// Database context for VDMA LIF 1.0.0 Map Manager
///
public class MapDbContext(DbContextOptions options) : DbContext(options)
{
// DbSets
public DbSet Layouts { get; set; } = null!;
public DbSet LayoutVersions { get; set; } = null!;
public DbSet LayoutLevels { get; set; } = null!;
public DbSet VehicleTypes { get; set; } = null!;
public DbSet Nodes { get; set; } = null!;
public DbSet Edges { get; set; } = null!;
public DbSet Stations { get; set; } = null!;
public DbSet StationInteractionNodes { get; set; } = null!;
public DbSet NodeVehicleProperties { get; set; } = null!;
public DbSet EdgeVehicleProperties { get; set; } = null!;
public DbSet LayoutLevelEditorSettings { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Layout configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => e.LayoutId).IsUnique();
entity.HasIndex(e => e.IsActive);
entity.HasMany(e => e.Versions)
.WithOne(e => e.Layout)
.HasForeignKey(e => e.LayoutId)
.OnDelete(DeleteBehavior.Cascade);
});
// LayoutVersion configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.LayoutId, e.Version }).IsUnique();
entity.HasIndex(e => e.IsActive);
entity.HasMany(e => e.Levels)
.WithOne(e => e.Version)
.HasForeignKey(e => e.VersionId)
.OnDelete(DeleteBehavior.Cascade);
});
// LayoutLevel configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.VersionId, e.LayoutLevelId }).IsUnique();
entity.HasIndex(e => e.LevelOrder);
entity.HasMany(e => e.Nodes)
.WithOne(e => e.Level)
.HasForeignKey(e => e.LevelId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.Edges)
.WithOne(e => e.Level)
.HasForeignKey(e => e.LevelId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.Stations)
.WithOne(e => e.Level)
.HasForeignKey(e => e.LevelId)
.OnDelete(DeleteBehavior.Cascade);
});
// VehicleType configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => e.VehicleTypeId).IsUnique();
entity.HasIndex(e => e.IsActive);
entity.HasMany(e => e.NodeVehicleProperties)
.WithOne(e => e.VehicleType)
.HasForeignKey(e => e.VehicleTypeId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.EdgeVehicleProperties)
.WithOne(e => e.VehicleType)
.HasForeignKey(e => e.VehicleTypeId)
.OnDelete(DeleteBehavior.Cascade);
});
// Node configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.LevelId, e.NodeId }).IsUnique();
entity.HasIndex(e => e.NodeId);
entity.HasIndex(e => e.MapId);
entity.HasIndex(e => new { e.X, e.Y });
entity.HasMany(e => e.VehicleProperties)
.WithOne(e => e.Node)
.HasForeignKey(e => e.NodeId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasMany(e => e.OutgoingEdges)
.WithOne(e => e.StartNode)
.HasForeignKey(e => e.StartNodeId)
.OnDelete(DeleteBehavior.Restrict);
entity.HasMany(e => e.IncomingEdges)
.WithOne(e => e.EndNode)
.HasForeignKey(e => e.EndNodeId)
.OnDelete(DeleteBehavior.Restrict);
entity.HasMany(e => e.StationInteractions)
.WithOne(e => e.Node)
.HasForeignKey(e => e.NodeId)
.OnDelete(DeleteBehavior.Restrict);
});
// Edge configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.LevelId, e.EdgeId }).IsUnique();
entity.HasIndex(e => e.EdgeId);
entity.HasIndex(e => e.StartNodeId);
entity.HasIndex(e => e.EndNodeId);
entity.ToTable(t => t.HasCheckConstraint("CK_Edges_DifferentNodes", "[StartNodeId] <> [EndNodeId]"));
entity.HasMany(e => e.VehicleProperties)
.WithOne(e => e.Edge)
.HasForeignKey(e => e.EdgeId)
.OnDelete(DeleteBehavior.Cascade);
});
// Station configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.LevelId, e.StationId }).IsUnique();
entity.HasIndex(e => e.StationId);
entity.HasMany(e => e.InteractionNodes)
.WithOne(e => e.Station)
.HasForeignKey(e => e.StationId)
.OnDelete(DeleteBehavior.Cascade);
});
// StationInteractionNode configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.StationId, e.NodeId }).IsUnique();
entity.HasIndex(e => e.StationId);
entity.HasIndex(e => e.NodeId);
});
// NodeVehicleProperty configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.NodeId, e.VehicleTypeId }).IsUnique();
entity.HasIndex(e => e.NodeId);
entity.HasIndex(e => e.VehicleTypeId);
});
// EdgeVehicleProperty configuration
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.HasIndex(e => new { e.EdgeId, e.VehicleTypeId }).IsUnique();
entity.HasIndex(e => e.EdgeId);
entity.HasIndex(e => e.VehicleTypeId);
});
// LayoutLevelEditorSettings configuration (UI extensions - not VDMA LIF)
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
// 1-to-1 relationship with LayoutLevel (unique index on LevelId)
entity.HasIndex(e => e.LevelId).IsUnique();
entity.HasOne(e => e.Level)
.WithOne(l => l.EditorSettings)
.HasForeignKey(e => e.LevelId)
.OnDelete(DeleteBehavior.Cascade);
});
}
}