IT story

엔티티 프레임 워크 코드 첫 번째-동일한 테이블에서 두 개의 외래 키

hot-time 2020. 4. 6. 08:12
반응형

엔티티 프레임 워크 코드 첫 번째-동일한 테이블에서 두 개의 외래 키


방금 EF 코드 사용을 시작 했으므로이 주제의 초보자입니다.

팀과 경기 사이의 관계를 만들고 싶었습니다.

1 경기 = 2 팀 (홈, 게스트) 및 결과.

그런 모델을 만드는 것이 쉽다고 생각하여 코딩을 시작했습니다.

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<Match> HomeMatches { get; set; }
    public virtual ICollection<Match> 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<Match>()
                    .HasRequired(m => m.HomeTeam)
                    .WithMany(t => t.HomeMatches)
                    .HasForeignKey(m => m.HomeTeamId)
                    .WillCascadeOnDelete(false);

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

기본 키는 기본 규칙에 따라 매핑됩니다. 팀에는 두 개의 경기 컬렉션이 있어야합니다. 두 개의 FK가 참조하는 단일 컬렉션을 가질 수 없습니다. 이 자체 참조 다 대다에서는 작동하지 않기 때문에 연속 삭제없이 일치가 매핑됩니다.


ForeignKey()탐색 속성 에서 속성 을 지정할 수도 있습니다 .

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

그렇게하면 OnModelCreate메소드에 코드를 추가 할 필요가 없습니다


나는 그것이 몇 년 된 게시물이라는 것을 알고 있으며 위의 해결책으로 문제를 해결할 수 있습니다. 그러나 여전히 필요한 사람에게 InverseProperty를 사용하는 것이 좋습니다. 적어도 OnModelCreating에서 아무것도 변경할 필요가 없습니다.

아래 코드는 테스트되지 않았습니다.

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

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

    [InverseProperty("GuestTeam")]
    public virtual ICollection<Match> 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; }
}

MSDN의 InverseProperty에 대한 자세한 내용은 https://msdn.microsoft.com/en-us/data/jj591583?f=255&MSPPError=-2147217396#Relationships를 참조하십시오.


당신도 이것을 시도 할 수 있습니다 :

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

FK 열에서 NULLS를 허용하면주기가 중단됩니다. 또는 우리는 EF 스키마 생성기를 속이고 있습니다.

내 경우에는이 간단한 수정으로 문제가 해결됩니다.


Cascade Deletes는 기본적으로 활성화되어 있기 때문입니다. 문제는 엔터티에서 삭제를 호출하면 각 f 키 참조 엔터티도 삭제한다는 것입니다. 이 문제를 해결하기 위해 '필수'값을 널 입력 가능으로 설정해서는 안됩니다. 더 좋은 옵션은 EF Code First의 Cascade 삭제 규칙을 제거하는 것입니다.

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

매핑 / 구성 할 때 각 자식에 대해 연속 삭제를 수행 할시기를 명시 적으로 표시하는 것이 더 안전 할 것입니다. 실체.


InverseProperty EF Core는 솔루션을 쉽고 깨끗하게 만듭니다.

InverseProperty

따라서 원하는 해결책은 다음과 같습니다.

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

    [InverseProperty(nameof(Match.HomeTeam))]
    public ICollection<Match> HomeMatches{ get; set; }

    [InverseProperty(nameof(Match.GuestTeam))]
    public ICollection<Match> AwayMatches{ get; set; }
}


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

    [ForeignKey(nameof(HomeTeam)), Column(Order = 0)]
    public int HomeTeamId { get; set; }
    [ForeignKey(nameof(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 Team HomeTeam { get; set; }
    public Team GuestTeam { get; set; }
}

참고 URL : https://stackoverflow.com/questions/5559043/entity-framework-code-first-two-foreign-keys-from-same-table

반응형