儿童实体的继承和导航属性



我在使用继承时对导航属性有问题(TPH-目前在EF Core中唯一可用)。

我的层次结构模型:

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-引用员工实体。在员工模型中,我想拥有两个导航属性来加载创建的儿童类型的建议:

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

,但会导致迁移错误。应用迁移后,我在提案表中有两个引用对员工实体(Creatorid,雇员)而不是一个(Creatsorid)。当我将导航属性更改为:

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

模型是正确的(只有一个对员工内部提案表的引用),但是我仍然无法将()分别添加到员工模型creatspropopopopopopopopopopopopopoposaleaves中。

问题可能在我的dbcontext配置内部,但我不知道如何正确设置它:/

问题是,当您必须导航属性时,EF Core还将创建两个外键,如您已经发现。

一个解决方法可能是拥有非映射导航属性,这只是将您的收藏品铸造与基类包装。

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()

相关内容

  • 没有找到相关文章

最新更新