5

상속 (TPH - 현재 EF 코어에서만 사용 가능한)을 사용하는 동안 탐색 속성에 문제가 있습니다.자식 엔터티에 대한 상속 및 탐색 속성

내 계층 구조 모델 :

public class Proposal 
{ 
    [Key] 
    public int ProposalId { get; set; } 

    [Required, Column(TypeName = "text")] 
    public string Substantiation { get; set; } 

    [Required] 
    public int CreatorId { get; set; } 

    [ForeignKey("CreatorId")] 
    public Employee Creator { get; set; } 

} 

public class ProposalLeave : Proposal 
{ 
    [Required] 
    public DateTime LeaveStart { get; set; } 

    [Required] 
    public DateTime LeaveEnd { get; set; } 
} 

public class ProposalCustom : Proposal 
{ 
    [Required, StringLength(255)] 
    public string Name { get; set; } 

} 

그리고 DbContext의 일부 :

public class AppDbContext : IdentityDbContext<User, Role, int> 
{ 

    public DbSet<Employee> Employee { get; set; } 
    public DbSet<Proposal> Proposal { get; set; } 

    public AppDbContext(DbContextOptions<AppDbContext> options) 
     : base(options) 
    { 
    } 

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

     modelBuilder.Entity<Proposal>() 
      .HasDiscriminator<string>("proposal_type") 
      .HasValue<Proposal>("proposal_base") 
      .HasValue<ProposalCustom>("proposal_custom") 
      .HasValue<ProposalLeave>("proposal_leave"); 

    } 
} 

좋아,의이 지점에 도착하자. 부모 제안 모델 내에서 볼 수 있듯이 CreatorId 속성 - Employee 엔티티에 대한 참조입니다. 직원 모델 내부에서 나는 다음과 같이 하위 유형의 생성 된 제안서를로드하는 두 개의 탐색 속성을 갖고 싶어 :

public class Employee 
{ 
    public ICollection<ProposalCustom> CreatedProposalCustoms { get; set; } 
    public ICollection<ProposalLeave> CreatedProposalLeaves { get; set; } 

} 

을하지만 마이그레이션 오류가 발생합니다. 마이그레이션을 적용한 후 CreatorId (CreatorId) 대신 Proposal 테이블에 Employee 엔티티 (CreatorId, EmployeeUserId)에 대한 참조가 두 개 있습니다. I가 탐색 속성을 변경하는 경우 :

public class Employee 
{  
    public ICollection<Proposal> CreatedProposals { get; set; } 
} 

모델 (제안 테이블 내부 직원 만 하나의 참조가 있었다) 정확했다,하지만, 난 여전히 별도로 직원 모델 CreatedProposalCustoms 및 CreatedProposalLeaves에() 포함 할 수 없습니다.

문제는 내 DbContext 구성 안에 아마도,하지만 난 방법을 정확하게 설정을 아무 생각이 :/

+1

추가'public DbSet ProposalLeaves {get; 세트; }'및'public DbSet ProposalCustoms {get; 세트; }'를 당신의 AppDbContext 클래스에 추가한다. 그런 다음'Employee'에 탐색 속성을 만들 수 있습니다. 그리고 그것들을'가상적 '으로 만들어라. – Kos

+0

추가에 동의하지만 실제로 게으른로드를 목표로하지 않는 한 가상으로 만들지는 않습니다. – Zephire

+0

@Kos 변경 사항을 적용했지만 여전히 작동하지 않습니다. .Include (e => e.CreatedLeaves)'는 항상 빈리스트를 제공하고, '_context.ProposalLeave.Where (pl => pl.CreatorId == emp.UserId) .ToList();'와'_context.Proposal.OfType (). (pl => pl.CreatorId == emp.UserId) .ToList()'는 잘 작동합니다./오, 그리고 여전히 불필요한 EmployeeUserId가 제안 테이블에 있습니다. – Kuba

답변

3

문제는 당신이 탐색 속성에있을 때, EF 코어는 또한 같은 두 개의 외래 키를 만들 것입니다 이미 알아 냈어.

한 가지 해결 방법은 기본 클래스로 컬렉션의 캐스팅을 래핑하는 non-mapped navigation properties 일 수 있습니다.

public class Employee 
{ 
    public IDbSet<Proposal> Proposals { get; set; } 
    [NotMapped] 
    public IQueryable<ProposalCustom> CreatedProposalCustoms { get; } => Proposals.OfType<ProposalCustom>(); 
    [NotMapped] 
    public IQueryable<ProposalLeave> CreatedProposalLeaves { get; } => Proposals.OfType<ProposalLeave>(); 
} 

어디 당신이 더 일반적인하려는 경우 두 매핑되지 않은 특성이 단지 Proposals.OfType<T>()

에 대한 속기의 역할 또는 것 :

public class Employee 
{ 
    public IDbSet<Proposal> Proposals { get; set; } 
    public IQueryable<T> AllProposals<T>() where T :Proposal => Proposals.OfType<T>(); 
} 

다음 employee.AllProposals<ProposalLeave>().Where(p => p.LeaveStart >= DateTime.Now).ToListAsync()로 사용합니다.

+0

감사합니다. 그것은 내 문제를 전혀 해결하지 못했지만 실제로 도움이되었다.) – Kuba