EF Core 3.1.7 테이블의 여러 1 : 1 관계에 대한 데이터 주석
EF Core 3.11.7이이를 이해하고 마이그레이션을 빌드 할 수 있도록 둘 이상의 1 : 1 관계를 매핑하는 데이터 주석을 파악하는 데 문제가 있습니다.
Person 테이블과 Notes 테이블이 있습니다. Person에는 0 : M Notes 관계가 있습니다. 개인 레코드에는 0 개 이상의 메모가있을 수 있습니다.
메모 테이블에는 사람인 CreatedBy 필드가 있습니다. 또한 사람인 LastEditedBy 필드도 있습니다. EF는 Note.CreatedBy에 대한 관계를 구성하는 방법에 대해 계속해서 공격하고 있습니다. 이것이 EF가 아닌 경우 두 필드 모두 적절한 개인 레코드의 PersonID가있는 int가됩니다. 데이터 주석을 선호하는 방식으로 EF Core에이를 설명하는 방법은 무엇입니까?
마이그레이션을 만들려고하면 실패하고 다음과 같이 표시됩니다. System.InvalidOperationException : 'Person'유형의 탐색 속성 'Note.CreatedBy'가 나타내는 관계를 확인할 수 없습니다. 관계를 수동으로 구성하거나 '[NotMapped]'속성을 사용하거나 'OnModelCreating'에서 'EntityTypeBuilder.Ignore'를 사용하여이 속성을 무시하십시오.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace VetReg.Domain.Model
{
public class Family
{
public int FamilyID { get; set; } = -1;
public string FamilyName { get; set; }
public List<Pet> Pets { get; set; } = new List<Pet>();
public List<PersonFamily> People { get; set; }
public int AddressID { get; set; } = -1;
public List<Note> Notes { get; set; }
}
public class Person
{
public int PersonID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime? Birthdate { get; set; }
public string Password { get; set; }
public List<PersonFamily> Families { get; set; }
public List<Note> Notes { get; set; }
} // class People
public class Note
{
public int NoteID { get; set; }
public int CreatedByID { get; set; }
[ForeignKey("CreatedByID")]
public Person CreatedBy { get; set; }
public DateTime DateCreated { get; set; }
public int LastEditByID { get; set; }
[ForeignKey("LastEditByID")]
public Person LastEditBy { get; set; }
public DateTime? LastEditDate { get; set; }
public string NoteText { get; set; }
}
public class PersonFamily
{
public int PersonID { get; set; }
public int FamilyID { get; set; }
public Person Person { get; set; }
public Family Family { get; set; }
}
}
답변
질문은 (그리고 이것이 EF가 관계를 자동으로 결정하는 것을 불가능하게 만드는 것입니다) Person.Notes
그리고 Note.CreatedBy
/ Note.LastEditBy
-아마 사이의 관계는 무엇 입니까? M의 관계 : 당신은 0이 말한 Person
과 Note
- 사람과 관련된 노트, 3 FKS과 사람, 잠재적으로 리드에 의해 편집 사람 및 메모에 의해 생성 한 메모 만이 3 일대 다 관계가 잠재적으로 있다는 것을 참고 메모에있는 사람.
또한 탐색 속성은 필요하지 않지만 존재하는 경우 쌍을 이루어야합니다.
사이에 관계가없는 즉, 당신이 세 관계를 원하는 가정 Note.CreatedBy
/ Note.LastEditBy
와 Person.Notes
, 그 EF 말할 필요 Note.CreatedBy
와 Note.LastEditBy
대응에 (일명 역) 탐색 속성이 없습니다 Person
. 데이터 주석으로는 불가능합니다. 이 목적을 위해 사용 가능한 유일한 데이터 주석은 [InverseProperty(...)]
비어있는 / 널 문자열 이름을 허용하지 않으므로 여기에서 필요한 항목에 사용할 수 없습니다.
또한 현재를 해결 한 후 발생하는 또 다른 문제가 있습니다.이 문제는 데이터 주석으로도 해결할 수 없습니다. 에서까지 여러 필수 (기본적으로 계단식 삭제) 관계가 Person
있으므로 Note
SqlServer에 유명한 "주기 또는 다중 계단식 경로"문제가 발생하고 계단식 삭제 중 하나 이상을 해제해야합니다.
따라서 해당 모델에는 다음과 같은 최소한의 유창한 구성이 필요합니다.
modelBuilder.Entity<Note>()
.HasOne(e => e.CreatedBy)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Note>()
.HasOne(e => e.LastEditBy)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
원래 문제의 핵심은 HasOne
/ WithMany
쌍입니다. 이렇게하면 EF Core는 매핑되지 않은 Person.Notes
컬렉션을 "PersonId"라는 역방향 탐색 속성과 섀도 FP 속성 (및 열)이없는 세 번째 선택적 관계에 자동으로 매핑합니다.
modelBuilder.Entity<Person>()
.HasMany(e => e.Notes)
.WithOne()
.HasForeignKey("PersonId");
다중 계단식 경로의 두 번째 문제와 관련하여 Restrict
비 계단식 옵션 또는 최신 ClientCascade
. 그리고 그것은 "계단 경로"를 깨는 즉시 관계 중 하나에 대한 것일 수 있습니다 (분명히 모델에서 요구하기 때문에 사이클을 깨뜨릴 수 없습니다).