Основы сущности кода Первый - две внешние ключи из одной таблицы

Я'вэ только начал использовать первый код в EF, так что я'м полный новичок в этой теме.

Я хотел создать отношения между командами и матчи:

1 матч = 2 команды (домашняя, гостевая) и результат.

Я думал, что это's легкий для того чтобы создать подобную модель, поэтому я начала писать:

public class Team
{
    [Key]
    public int TeamId { get; set;} 
    public string Name { get; set; }

    public virtual ICollection<Match> Matches { get; set; }
}

public class Match
{
    [Key]
    public int MatchId { get; set; }

    [ForeignKey("HomeTeam"), Column(Order = 0)]
    public int HomeTeamId { get; set; }
    [ForeignKey("GuestTeam"), Column(Order = 1)]
    public int GuestTeamId { get; set; }

    public float HomePoints { get; set; }
    public float GuestPoints { get; set; }
    public DateTime Date { get; set; }

    public virtual Team HomeTeam { get; set; }
    public virtual Team GuestTeam { get; set; }
}

И я получаю исключение:

референциальных отношений приведет к циклической ссылкой, что не допускается. [ Имя ограничения = Match_GuestTeam ]

Как я могу создать такую модель, с 2 внешних ключей в одной таблице?

Решение

Попробуйте это:

public class Team
{
    public int TeamId { get; set;} 
    public string Name { get; set; }

    public virtual ICollection HomeMatches { get; set; }
    public virtual ICollection AwayMatches { get; set; }
}

public class Match
{
    public int MatchId { get; set; }

    public int HomeTeamId { get; set; }
    public int GuestTeamId { get; set; }

    public float HomePoints { get; set; }
    public float GuestPoints { get; set; }
    public DateTime Date { get; set; }

    public virtual Team HomeTeam { get; set; }
    public virtual Team GuestTeam { get; set; }
}

public class Context : DbContext
{
    ...

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity()
                    .HasRequired(m => m.HomeTeam)
                    .WithMany(t => t.HomeMatches)
                    .HasForeignKey(m => m.HomeTeamId)
                    .WillCascadeOnDelete(false);

        modelBuilder.Entity()
                    .HasRequired(m => m.GuestTeam)
                    .WithMany(t => t.AwayMatches)
                    .HasForeignKey(m => m.GuestTeamId)
                    .WillCascadeOnDelete(false);
    }
}

Первичные ключи сопоставляются по Конвенции по умолчанию. Команда должна иметь две коллекции спичек. Вы можете'т иметь единый сборник, на которые ссылаются два ФКС. Матч отображается без каскадное удаление, потому что он не't работа в эти ссылки многие-ко-многим.

Комментарии (10)

Это's также можно указать атрибут отношения foreignkey () на свойство навигации:

[ForeignKey("HomeTeamID")]
public virtual Team HomeTeam { get; set; }
[ForeignKey("GuestTeamID")]
public virtual Team GuestTeam { get; set; }

Таким образом, вы Дон'т нужно добавить любой код в OnModelCreate метод

Комментарии (3)

Я знаю, что это'ы на несколько лет поста и вы можете решить вашу проблему с выше решение. Однако, я просто хочу предложить, используя InverseProperty для кого-то, кто все-таки нужен. По крайней мере, вы не'т нужно ничего менять в OnModelCreating.

Приведенный ниже код является непроверенному.

public class Team
{
    [Key]
    public int TeamId { get; set;} 
    public string Name { get; set; }

    [InverseProperty("HomeTeam")]
    public virtual ICollection HomeMatches { get; set; }

    [InverseProperty("GuestTeam")]
    public virtual ICollection GuestMatches { get; set; }
}

public class Match
{
    [Key]
    public int MatchId { get; set; }

    public float HomePoints { get; set; }
    public float GuestPoints { get; set; }
    public DateTime Date { get; set; }

    public virtual Team HomeTeam { get; set; }
    public virtual Team GuestTeam { get; set; }
}

Вы можете прочитать больше о InverseProperty на MSDN: https://msdn.microsoft.com/en-us/data/jj591583?f=255&MSPPError=-2147217396#отношения

Комментарии (4)

Вы тоже можете попробовать это:

public class Match
{
    [Key]
    public int MatchId { get; set; }

    [ForeignKey("HomeTeam"), Column(Order = 0)]
    public int? HomeTeamId { get; set; }
    [ForeignKey("GuestTeam"), Column(Order = 1)]
    public int? GuestTeamId { get; set; }

    public float HomePoints { get; set; }
    public float GuestPoints { get; set; }
    public DateTime Date { get; set; }

    public virtual Team HomeTeam { get; set; }
    public virtual Team GuestTeam { get; set; }
}

Когда вы делаете ФК столбец допускает значения null, вы нарушаете цикл. Или нас просто обманывают генератор эф схемы.

В моем случае, это простая модификация решит проблему.

Комментарии (1)

Это потому, что каскадное удаление по умолчанию включены. Проблема в том, что при вызове Delete на объект, он будет удалять каждый из F-клавиш, на которые ссылается лиц, а также. Вы не должны 'требуется' nullable значения для решения этой проблемы. Лучшим вариантом будет снять эф код первого'ы каскадное удаление конвенции:

modelBuilder.Conventions.Remove(); 

Это'ы, вероятно, безопаснее, чтобы явно указать, когда, чтобы сделать каскадное удаление для каждого из детей, когда отображение/конфигурация. сущность.

Комментарии (1)

`InverseProperty в эф ядра делает решение простым и чистым.

InverseProperty

Так что искомое решение будет:

`` группа открытый класс { [Ключ] TeamId публичных инт { получить; набор;} имя строку { получить; набор; }

[InverseProperty(именемна(матч.Команда хозяев поля))] публичный интерфейс ICollection<матч> HomeMatches{ получить; набор; }

[InverseProperty(именемна(матч.GuestTeam))] публичный интерфейс ICollection<матч> AwayMatches{ получить; набор; } }

матч Открытый класс { [Ключ] MatchId публичных инт { получить; набор; }

[Отношения foreignkey(имя(команда хозяев поля)), колонки(порядок = 0)] HomeTeamId публичных инт { получить; набор; } [Отношения foreignkey(функция nameof(GuestTeam)), колонки(заказ = 1)] общественный инт GuestTeamId { получить; набор; }

HomePoints публичных поплавок { получить; набор; } GuestPoints публичных поплавок { получить; набор; } дата общественная datetime { получить; набор; }

команды команды хозяев поля { получить; набор; } общественные группы GuestTeam { получить; набор; } } ``

Комментарии (0)