Как реально работают циклы и несколько каскадных путей в EF Core - PullRequest
1 голос
/ 14 марта 2019

Может ли кто-нибудь объяснить мне, почему у меня возникает эта ошибка.

Введение ограничения FOREIGN KEY 'FK_CommentMention_User_UserId' для таблицы 'CommentMention' может вызвать циклы или несколько каскадных путей.

public class Comment
{
    public int Id { get; set; }

    [Required]
    public string Message { get; set; }

    public DateTimeOffset CreationDate { get; set; } = DateTimeOffset.UtcNow;

    public int? CandidatureId { get; set; }
    public Candidature Candidature { get; set; }

    public int AuthorId { get; set; }
    public User Author { get; set; }

    public IList<CommentMention> MentionedUsers { get; set; } = new List<CommentMention>();
}

public class CommentMention
{
    public int CommentId { get; set; }
    public Comment Comment{ get; set; }

    public int UserId { get; set; } // That's the foreign property which cause the error
    public User User { get; set; }
}

public class User
{
    public int Id { get; set; }

    [Required]
    public string Email { get; set; }

    [Required]
    public string PasswordHash { get; set; }

    [Required]
    public string FirstName { get; set; }

    [Required]
    public string MiddleName { get; set; }

    [Required]
    public string LastName { get; set; }

    [Required]
    public string Phone { get; set; }

    [Required]
    public string Role { get; set; }

    public bool Disabled { get; set; } = false;

    public DateTimeOffset CreationDate { get; set; } = DateTimeOffset.UtcNow;

    public int? CompanyId { get; set; }
    public Company Company { get; set; }

    public int? CreatedByUserId { get; set; }
    public User CreatedByUser { get; set; }

    public IList<User> SubUsers { get; set; } = new List<User>();

    [InverseProperty("CreatedByUser")]
    public IList<Candidature> CreatedCandidatures { get; set; } = new List<Candidature>();

    [InverseProperty("Lawyer")]
    public IList<Candidature> LawyerCandidatures { get; set; } = new List<Candidature>();

    [InverseProperty("Agent")]
    public IList<Candidature> AgentCandidatures { get; set; } = new List<Candidature>();

    public IList<UserDocument> Documents { get; set; } = new List<UserDocument>();

    public IList<Comment> Comments { get; set; } = new List<Comment>();

    public IList<Event> Events { get; set; } = new List<Event>();

    public IList<Reminder> Reminders { get; set; } = new List<Reminder>();

    public IList<CommentMention> Mentions { get; set; } = new List<CommentMention>();

    [InverseProperty("Owner")]
    public IList<Notification> Notifications { get; set; } = new List<Notification>();

    [NotMapped]
    public string FullName => this.FirstName + " " + this.LastName;
}

На самом деле вопрос не в том, как это исправить, потому что я уже знаю решение, которое заключается в добавлении ограниченного поведения удаления.

modelBuilder.Entity<CommentMention>()
    .HasOne(x => x.User)
    .WithMany(x => x.Mentions)
    .HasForeignKey(x => x.UserId)
    .OnDelete(DeleteBehavior.Restrict);

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

Давайте рассмотрим возможные варианты удаления:

  1. Запись в CommentMention удалена: каскадное удаление отсутствует, потому что это дочернее / зависимоеentity.
  2. Запись в комментарии удаляется: каскадное удаление освобожденных записей в CommentMention.
  3. Запись в пользователе удаляется: каскадное удаление выпущенных записей в кандидатуре, UserDocument, Comment, Event,Напоминание, CommentMention и таблицы уведомлений.

Также мне интересно,между циклами и несколькими существует разное, поскольку между ними есть ключевое слово 'или', что означает, что это два возможных каскадных пути.

Диаграмма этих таблиц: diagram

1 Ответ

1 голос
/ 14 марта 2019

Скажем, вы удаляете пользователя.Это заставляет вас удалять их CommentMentions через userID в таблице.

Но это также заставляет вас удалять комментарии, которые они создали, что, в свою очередь, означает, что мы должныудалить CommentMentions через CommentId.

Два различных каскадных пути, которые приводят к попыткам удаления в CommentMentions.

Цикла дляэтот.Ты прав.SQL Server использует одно сообщение для покрытия двух разных сценариев, но также могут быть сценарии, в которых применяются обе части сообщения do .

У вас будет цикл для CreatedByUserId иностранногоключ, если вы пытались применить к нему каскадные удаления.


Это легче всего увидеть, посмотрев на диаграмму.Выберите направление для ввода внешних ключей - либо всегда к ключу, либо всегда к ... другому концу 1 .

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


1 Я никогда не понимал, что должен означать другой конец этих строк.Это ссылка на цепочку?Символ бесконечности?Что-то еще?

...