방금 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는 솔루션을 쉽고 깨끗하게 만듭니다.
따라서 원하는 해결책은 다음과 같습니다.
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; }
}