Удаление списка в таблице приводит к ошибке SQL - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть проект .NetCore Entity Framework для модельного аэропорта.

Когда я пытаюсь удалить аэропорт в списках, я получаю сообщение об ошибке ниже при попытке удалить авиакомпанию, и я пытаюсь чтобы выяснить, почему:

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; }
}

И AirlinePilots

    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; }
}

Мой контекстный класс БД выглядит следующим образом для Airline:

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 - это просто справочная таблица, в которой хранится AirlineId для каждого PilotId. Одна авиакомпания может иметь много пилотов. У него есть внешний ключ для AirlineId и один для PilotId.

В моей базе данных у авиакомпании нет внешнего ключа для AirlinePilots. Однако таблица AirlinePilots имеет внешний ключ для Airline.

Таким образом, для действия DELETE в API потребуется удалить Airline и все связанные строки, содержащие идентификатор Airline, которые удаляются в таблице AirlinePilots.

Я действительно боюсь что-либо изменить, потому что не хочу, чтобы он случайно удалил все из таблицы AirlinePilots.

Можно ли что-нибудь добавить в свой контекстный класс, чтобы эта работа работала? ?

спасибо! :)

1 Ответ

3 голосов
/ 25 апреля 2020

AirlineId не является обнуляемым внешним ключом на AirlinePilots, поэтому вы не можете использовать ClientSetNull, потому что он вызывает SaveChanges, что вам нужно, это каскадное удаление, которое достигается с помощью Cascade опции для сопоставления Airline fk .:

.OnDelete(DeleteBehavior.Cascade) 

Кстати, из вашего сопоставления я понимаю, что вы также контролируете эту коллекцию от объекта Pilot, обычно это недостаток дизайна, который может вызвать проблемы в будущем, у вас может закончиться тот же предмет загружается дважды в памяти, указывая на одну и ту же строку базы данных, где могут возникнуть проблемы с параллелизмом. Если вам нужно показать авиакомпании из Pilot, воспользуйтесь запросом, чтобы вместо этого вернуть объекты только для чтения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...