Почему SQL Server не может обрабатывать каскадные удаления для двух внешних ключей, указывающих на одну и ту же таблицу? - PullRequest
2 голосов
/ 11 мая 2011

Я использую Entity Framework - Code First, и я столкнулся с проблемой, когда мне нужно отключить каскадное удаление для определенного внешнего ключа.

Вот мой класс сущности:

public class ChallengeMatch
{
    public int Id { get; set; }
    public int ChallengerClubMemberId { get; set; }
    public int ChallengeeClubMemberId { get; set; }
    public bool ChallengerWon { get; set; }
    public string Score { get; set; }

    public virtual ClubMember ChallengerClubMember { get; set; }
    public virtual ClubMember ChallengeeClubMember { get; set; }
}

Если я позволю Code First сгенерировать базу данных для этой таблицы со всеми настройками по умолчанию (включая каскадное удаление), она выдаст исключение при попытке создать объекты базы данных.

Если я добавлю следующий код в мой класс DbContext, я больше не получу исключение, но теперь каскадное удаление будет работать только в некоторой степени :

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<ChallengeMatch>()
        .HasRequired(cm => cm.ChallengeeClubMember)
        .WithMany()
        .HasForeignKey(cm => cm.ChallengeeClubMemberId)
        .WillCascadeOnDelete(false);
}

Из-за этого мне приходится писать код вручную. В частности, если я собираюсь удалить ClubMember 13, я должен удалить любой ChallengeMatch, чей ChallengeeClubMemberId равен 13.

Что я не понимаю, так это то, почему все это необходимо. Почему SQL Server не может обработать каскадное удаление, даже если два внешних ключа указывают на одну и ту же таблицу? Я не могу придумать причину, по которой это не получится.

Это должен быть простой трехэтапный процесс (псевдо-код):

  1. Удалить все вызовы, где ChallengerClubMemberId == 13
  2. Удалить все вызовы, где ChallengeeClubMemberId == 13
  3. Удалить члена клуба, где Id = 13.

Почему SQL Server не может этого сделать или почему он этого не делает?

1 Ответ

2 голосов
/ 11 мая 2011

Проблема в том, что ваша конфигурация позволяет использовать несколько путей каскадного удаления.Это может произойти, если оба ваших свойства будут указывать на один и тот же ClubMember.SQL Server не позволяет этого.Это больше о внутренней реализации SQL-сервера и более подробную информацию можно найти в этот ответ .Я думаю, что эта проверка является простым и безопасным решением, позволяющим избежать некоторых условий гонки во время параллельного удаления каскадов.

...