首页 > 解决方案 > 删除表中的列表会引发 SQL 错误

问题描述

我有一个模型机场的 .NetCore 实体框架项目。

当我尝试删除列表中的机场时,尝试删除航空公司时出现以下错误,我试图找出原因:

Microsoft.Data.SqlClient.SqlException (0x80131904): The DELETE statement conflicted with the REFERENCE constraint "FK_airlinePilots_airline". The conflict occurred in database "FrankAirportTeam", table "dbo.airlinePilots", column 'airlineId'.

删除操作只是一个 API 方法:

    [HttpDelete("{id}")]
    public async Task<ActionResult<Airline>> DeleteAirline(long id)
    {
        var airline = await _context.Airline.FindAsync(id);
        if (airline == null)
        {
            return NotFound();
        }

        _context.Airline.Remove(airline);
        await _context.SaveChangesAsync();

        return airline;
    }

我的航空公司模型如下:

public partial class Airline
{
    public Airline()
    {
        AirlinePilots = new HashSet<AirlinePilots>();
    }

    public long Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public long CityId { get; set; }

    public virtual City City { get; set; }
    public virtual ICollection<AirlinePilots> AirlinePilots { get; set; }
}

和航空公司飞行员

    public partial class AirlinePilots
{
    public long PilotId { get; set; }
    public long AirlineId { get; set; }

    public virtual Airline Airline { get; set; }
    public virtual Pilot Pilot { get; set; }
}

对于航空公司,我的数据库上下文类如下所示:

modelBuilder.Entity<Airline>(entity =>
        {
            entity.ToTable("airline");

            entity.HasIndex(e => e.Id)
                .HasName("IX_airline");

            entity.Property(e => e.Id)
                .HasColumnName("id");

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

            entity.Property(e => e.CityId).HasColumnName("cityId");

            entity.Property(e => e.Title)
                .IsRequired()
                .HasColumnName("title")
                .HasMaxLength(255);

            entity.HasOne(d => d.City)
                .WithMany(p => p.Airline)
                .HasForeignKey(d => d.CityId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_airline_city");
        });

在 AirlinePilots [使用新删除方法更新]:

        modelBuilder.Entity<AirlinePilots>(entity =>
        {
            entity.HasKey(e => new { e.PilotId, e.AirlineId });

            entity.ToTable("airlinePilots");

            entity.Property(e => e.PilotId).HasColumnName("pilotId");

            entity.Property(e => e.AirlineId).HasColumnName("airlineId");

            entity.HasOne(d => d.Airline)
                .WithMany(p => p.AirlinePilots)
                .HasForeignKey(d => d.AirlineId)
                .OnDelete(DeleteBehavior.Cascade)
                .HasConstraintName("FK_airlinePilots_airline");

            entity.HasOne(d => d.Pilot)
                .WithMany(p => p.AirlinePilots)
                .HasForeignKey(d => d.PilotId)
                .OnDelete(DeleteBehavior.Cascade)
                .HasConstraintName("FK_airlinePilots_pilot");
        });

AirlinePilots 只是一个查找表,它为每个 PilotId 存储一个 AirlineId。一家航空公司可以有多名飞行员。它有一个用于 AirlineId 的外键和一个用于 PilotId 的外键。

在我的数据库中,航空公司没有 AirlinePilots 的外键。但是,AirlinePilots 表确实有一个 Airline 的外键。

因此,API 中的 DELETE 操作需要删除 Airline 以及包含正在 AirlinePilots 表中删除的 Airline Id 的任何关联行。

实际上,我真的很害怕更改任何内容,因为我不希望它意外删除 AirlinePilots 表中的所有内容。

有什么我可以添加到我的上下文类中来完成这项工作的吗?

谢谢!:)

标签: entity-frameworkasp.net-coreentity-framework-coreasp.net-core-webapiasp.net-core-3.0

解决方案


AirlineId 在 AirlinePilots 上不是可为空的外键,因此您不能使用 ClientSetNull,因为它会引发 SaveChanges,您需要的是使用Airline fk 映射的Cascade选项实现的级联删除行为。:

.OnDelete(DeleteBehavior.Cascade) 

顺便说一句,从你的映射中,我知道你也在从 Pilot 实体控制这个集合,通常这是一个设计缺陷,可能会给你带来麻烦,你可能会在内存中加载相同的项目两次,指向同一个数据库行,可能会出现并发问题的地方。如果您需要从 Pilot 显示航空公司,则使用查询来返回只读实体。


推荐阅读