MapNodeConfiguration.cs 3.81 KB
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Rcs.Domain.Entities;

namespace Rcs.Infrastructure.DB.Configuration.Domain
{
    /// <summary>
    /// MapNode实体的EF Core配置
    /// </summary>
    public class MapNodeConfiguration : IEntityTypeConfiguration<MapNode>
    {
        public void Configure(EntityTypeBuilder<MapNode> builder)
        {
            // 配置表名
            builder.ToTable("map_nodes");

            // 配置主键
            builder.HasKey(e => e.NodeId);

            // 配置属性
            builder.Property(e => e.NodeId)
                .HasColumnName("node_id")
                .ValueGeneratedNever();

            builder.Property(e => e.MapId)
                .HasColumnName("map_id")
                .IsRequired();

            builder.Property(e => e.NodeCode)
                .HasColumnName("node_code")
                .HasMaxLength(50)
                .IsRequired();

            builder.Property(e => e.NodeName)
                .HasColumnName("node_name")
                .HasMaxLength(100);

            builder.Property(e => e.Description)
                .HasColumnName("description");

            builder.Property(e => e.X)
                .HasColumnName("x")
                .IsRequired();

            builder.Property(e => e.Y)
                .HasColumnName("y")
                .IsRequired();

            builder.Property(e => e.Theta)
                .HasColumnName("theta");

            builder.Property(e => e.IsReverseParking)
                .HasColumnName("is_reverse_parking")
                .HasDefaultValue(false);

            builder.Property(e => e.AllowRotate)
                .HasColumnName("allow_rotate")
                .HasDefaultValue(false);

            builder.Property(e => e.MaxCoordinateOffset)
                .HasColumnName("max_coordinate_offset");

            builder.Property(e => e.Type)
                .HasColumnName("type")
                .IsRequired();

            builder.Property(e => e.Metadata)
                .HasColumnName("metadata")
                .HasColumnType("jsonb")
                .HasConversion(
                    v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null),
                    v => JsonSerializer.Deserialize<Dictionary<string, object>>(v, (JsonSerializerOptions?)null)!);

            builder.Property(e => e.CreatedAt)
                .HasColumnName("created_at")
                .HasColumnType("timestamp without time zone");

            builder.Property(e => e.Active)
                .HasColumnName("active")
                .HasDefaultValue(true);

            // 配置索引
            builder.HasIndex(e => e.MapId)
                .HasDatabaseName("idx_node_map");

            builder.HasIndex(e => new { e.MapId, e.NodeCode })
                .HasDatabaseName("idx_node_map_code");

            builder.HasIndex(e => e.Type)
                .HasDatabaseName("idx_node_type");

            // 配置导航属性 - 多对一关系
            builder.HasOne(e => e.Map)
                .WithMany(m => m.MapNodes)
                .HasForeignKey(e => e.MapId)
                .OnDelete(DeleteBehavior.Cascade);

            // 配置导航属性 - 一对多关系
            builder.HasMany(e => e.MapEdgesFromNodes)
                .WithOne(e => e.MapNodesFromNode)
                .HasForeignKey(e => e.FromNode)
                .OnDelete(DeleteBehavior.NoAction);

            builder.HasMany(e => e.MapEdgesToNodes)
                .WithOne(e => e.MapNodesToNode)
                .HasForeignKey(e => e.ToNode)
                .OnDelete(DeleteBehavior.NoAction);

            builder.HasOne(e => e.Robot)
                .WithOne()
                .HasForeignKey<MapNode>(e => e.RobotId)
                .OnDelete(DeleteBehavior.SetNull);
        }
    }
}