【问题标题】:Deleting a listing in table throws a SQL error删除表中的列表会引发 SQL 错误
【发布时间】:2020-08-08 08:44:17
【问题描述】:

我有一个用于模型机场的 .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-framework asp.net-core entity-framework-core asp.net-core-webapi asp.net-core-3.0


    【解决方案1】:

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

    .OnDelete(DeleteBehavior.Cascade) 
    

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

    【讨论】:

    • 哦,好的,所以对于我的 modelBuilder.Entity,将这个:.OnDelete(DeleteBehavior.ClientSetNull) 更改为 .OnDelete(DeleteBehavior.Cascade) 会摆脱那个错误吗?谢谢!
    • 关于你提到的第二期,你是指public virtual Airline Airline { get; 中的 Pilot 集合吗?放; } ?谢谢
    • 所以我将它在我的 dbcontext 类文件中删除的方式更改为 Cascade 方法。您可以在我上面的问题中看到更新的代码。但即使我改变了它,它仍然给我完全相同的错误。 :(
    • @SkyeBoniwell,您是否尝试从 Pilot 中删除该收藏?这样,只有航空公司将成为 AirlinePilots 集合的所有者。
    • 是的,还是同样的错误。我认为这只是一个 Sql Server 限制,所以我需要弄清楚如何在代码中做到这一点。
    猜你喜欢
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多