Entity Framework 4.1 Атрибут InverseProperty и ForeignKey

Я создам две ссылки между сущностями Employee и Team с внешними ключами. Таким образом, я определил два объекта следующим образом:

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }

    [ForeignKey("FirstTeam")]
    public int FirstTeamId { get; set; }

    [InverseProperty("FirstEmployees")]
    public virtual Team FirstTeam { get; set; }

    [ForeignKey("SecondTeam")]
    public int SecondTeamId { get; set; }

    [InverseProperty("SecondEmployees")]
    public virtual Team SecondTeam { get; set; }
}

public class Team
{
    public int Id { get; set; }
    public string TeamName { get; set; }

    [InverseProperty("FirstTeam")]
    public virtual ICollection<Employee> FirstEmployees { get; set; }

    [InverseProperty("SecondTeam")]
    public virtual ICollection<Employee> SecondEmployees { get; set; }
}

Я думал, что это правильно теоретически, но он показывает исключение следующим образом:

{"Introducing FOREIGN KEY constraint 'Employee_SecondTeam' on table 'Employees' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.\r\nCould not create constraint. See previous errors."}

Может кто-нибудь мне помочь?

Спасибо заранее Kwon

Ответ 1

Это теоретически правильно, но SQL-сервер (а не инфраструктура Entity) не нравится, потому что ваша модель позволяет одному сотруднику быть членом как первой, так и второй команды. Если элемент Team удален, это приведет к нескольким путям удаления к одному и тому же объекту Employee.

Это нельзя использовать вместе с каскадными удалениями, которые по умолчанию используются в EF-коде, если вы определяете внешний ключ как обязательный (не может быть нулевым).

Если вы хотите избежать исключения, вы должны использовать свободное отображение:

public Context : DbContext
{
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Team> Teams { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Employee>()
                    .HasRequired(e => e.SecondTeam)
                    .WithMany(t => t.SecondEmployees)
                    .HasForeignKey(e => e.FirstTeamId)
                    .WillCascadeOnDelete(false);

        ...
    }
}

Это приведет к сценарию, в котором вы должны удалить участников SecondTeam вручную, прежде чем удалять команду.

Ответ 2

В предыдущем ответе все правильно, но одно не так.

    modelBuilder.Entity<Employee>()
                .HasRequired(e => e.SecondTeam)
                .WithMany(t => t.SecondEmployees)
                .HasForeignKey(e => e.SecondTeamId) // mistake
                .WillCascadeOnDelete(false);

FirstTeamId вместо SecondTeamId приведет к тому, что свойство SecondTeam navigation всегда будет FirstTeam