C# 包括原因InvalidCastException

C# 包括原因InvalidCastException,c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,我对Entity Framework Core 1.1中的此查询有问题: var leaves = _context.Proposal.OfType<ProposalLeave>() .Include(l => l.Creator).ThenInclude(e => e.User) .Include(l=>l.LeaveType) // this include causes the exception

我对Entity Framework Core 1.1中的此查询有问题:

var leaves = _context.Proposal.OfType<ProposalLeave>()
                .Include(l => l.Creator).ThenInclude(e => e.User)
                .Include(l=>l.LeaveType) // this include causes the exception
                .Include(l => l.ProposalLeaveStatuses).ThenInclude(l => l.ProposalLeaveStatus)
                .ToList();
在我查询之前,它甚至可以与
.Include(l=>l.LeaveType)
一起使用,没有任何例外

我在EF github上发现了一些关于InvalidCastException的bug问题,但在EF Core1.1中,所有这些问题都被标记为已修复

@更新 在这里,您可以下载重现该问题的VS2015项目: . 设置:

  • 安装.Net Core 1.1。sdk与运行时
  • 在appsettings.json中创建空数据库并替换连接字符串
  • 在包管理器控制台中运行更新数据库
  • 运行项目

  • 不幸的是,我所能做的就是确认一个明显的事实,即问题是由EF核心缺陷引起的

    我能够将复制减少到以下内容:

    型号:

    查询:

    var proposalCustoms=db.Proposal.OfType()
    .包括(l=>l.ProposalType)
    .ToList();
    var proposalLeaves=db.Proposal.OfType()
    .包括(l=>l.LeaveType)
    .ToList();
    
    尽管
    ProposalCustom
    ProposalLeave
    看起来很相似,但第一个查询始终有效,第二个则无效(如下文所示,在某些情况下有效)

    为什么我肯定这是一个错误。首先,因为查询和/或模型/配置没有问题。看起来这是由几个因素的组合造成的,首先是TPH、派生类属性的数量和类型,以及派生实体的类名(字母顺序?)

    例如,如果没有
    LeaveEnd
    属性,则第二个查询可以工作。最有趣的部分(当然取决于视图)是,如果您将
    ProposalCustom
    类重命名为
    ProposalXCustom
    ,或
    ProposalLeave
    重命名为
    ProposalLeave
    ,换句话说,将有问题的实体类名称按字母顺序排在第一位(我知道这听起来很疯狂),在没有任何数据库结构/映射更改的情况下,查询工作正常


    我建议您将其报告给EF核心存储库<代码>证实列和
    必需
    /
    属性似乎不会影响行为。另外,请注意,第一个查询总是有效的,执行顺序并不重要

    没有完整的模型就无法复制。如果您注释掉
    .Include(l=>l.ProposalLeaveStatus)。然后注释掉Include(l=>l.ProposalLeaveStatus)
    行,会发生什么情况?@IvanStoev它仍然不起作用。只有删除行:
    Include(l=>l.LeaveType)
    才能解决我的问题。这就是我在问题中跳过ProposalLeaveStatus和ProposalLeaveStatus模型定义的原因。稍后,我将通过添加DbContextI的重要部分来更新我的问题。但这似乎会对过程产生某种影响,因为w/o
    。然后include(e=>e.User)
    和第一条评论中提到的行它不会发生,我的意思是,它在没有错误的情况下工作。@IvanStoev我添加了VS 2015项目,重现了我的问题。你能确认你有相同的错误,它可能是EF核心的问题吗?问题报告。谢谢你的帮助。
    public class Proposal
    {
        [Key]
        public int ProposalId { get; set; }
    
        [Required]
        public DateTime DateCreated { 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; }
    
        [Required]
        public int ProposalLeaveTypeId { get; set; }
    
        [ForeignKey("ProposalLeaveTypeId")]
        public virtual ProposalLeaveType LeaveType { get; set; }
    
        public virtual ICollection<ProposalLeaveStatuses> ProposalLeaveStatuses { get; set; }
    }
    
    public class ProposalLeaveType
    {
        [Key]
        public int LeaveTypeId { get; set; }
    
        [Required, StringLength(255)]
        public string Name { get; set; }
    
        [Required, Column(TypeName = "text")]
        public string Description { get; set; }
    
        public ICollection<ProposalLeave> ProposalLeaves { get; set; }
    }
    
    public class AppDbContext : IdentityDbContext<User, Role, int>
    {
    
        public DbSet<Proposal> Proposal { get; set; }
        public DbSet<ProposalLeaveStatus> ProposalLeaveStatus { get; set; }
        public DbSet<ProposalLeaveStatuses> ProposalLeaveStatuses { get; set; }
        public DbSet<ProposalLeaveType> ProposalLeaveType { get; set; }
    
    
        public AppDbContext(DbContextOptions<AppDbContext> options)
            : base(options)
        {
        }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            // proposal hierarchy
            modelBuilder.Entity<Proposal>()
                .HasDiscriminator<string>("proposal_type")
                .HasValue<Proposal>("proposal_base")
                .HasValue<ProposalCustom>("proposal_custom")
                .HasValue<ProposalLeave>("proposal_leave");
    
            // proposal statuses many to many
            modelBuilder.Entity<ProposalLeaveStatuses>()
                .HasOne(pt => pt.Proposal)
                .WithMany(p => p.ProposalLeaveStatuses)
                .HasForeignKey(pt => pt.ProposalId)
                .OnDelete(DeleteBehavior.Restrict);
    
            modelBuilder.Entity<ProposalLeaveStatuses>()
                .HasOne(pt => pt.ProposalLeaveStatus)
                .WithMany(t => t.ProposalLeaveStatuses)
                .HasForeignKey(pt => pt.ProposalLeaveStatusId);
    
            //Substantially, there are nothing about Proposal Leave Types, cause its relation one-to-many modeled using data annotations.
        }
    }
    
     var leaveTypes = _context.ProposalLeaveType.Include(plt => plt.ProposalLeaves).ToList();
    
    public class Proposal
    {
        [Key]
        public int ProposalId { get; set; }
    
        [Required, Column(TypeName = "text")]
        public string Substantiation { get; set; }
    
        public DateTime DateCreated { get; set; }
    }
    
    public class ProposalCustom : Proposal
    {
        [Required, StringLength(255)]
        public string Name { get; set; }
    
        public int ProposalTypeId { get; set; }
    
        [ForeignKey("ProposalTypeId")]
        public virtual ProposalCustomType ProposalType { get; set; }
    }
    
    public class ProposalCustomType
    {
        [Key]
        public int ProposalTypeId { get; set; }
    
        [Required, StringLength(255)]
        public string Name { get; set; }
    
        [Required, Column(TypeName = "text")]
        public string Description { get; set; }
    
        public ICollection<ProposalCustom> ProposalCustoms { get; set; }
    }
    
    public class ProposalLeave : Proposal
    {
        public DateTime LeaveStart { get; set; }
    
        public DateTime LeaveEnd { get; set; }
    
        public int ProposalLeaveTypeId { get; set; }
    
        [ForeignKey("ProposalLeaveTypeId")]
        public virtual ProposalLeaveType LeaveType { get; set; }
    }
    
    public class ProposalLeaveType
    {
        [Key]
        public int LeaveTypeId { get; set; }
    
        [Required, StringLength(255)]
        public string Name { get; set; }
    
        [Required, Column(TypeName = "text")]
        public string Description { get; set; }
    
        public ICollection<ProposalLeave> ProposalLeaves { get; set; }
    }
    
    public DbSet<Proposal> Proposal { get; set; }
    public DbSet<ProposalCustomType> ProposalCustomType { get; set; }
    public DbSet<ProposalLeaveType> ProposalLeaveType { get; set; }
    
    modelBuilder.Entity<Proposal>()
        .HasDiscriminator<string>("proposal_type")
        .HasValue<Proposal>("proposal_base")
        .HasValue<ProposalCustom>("proposal_custom")
        .HasValue<ProposalLeave>("proposal_leave");
    
    db.Proposal.Add(new ProposalLeave
    {
        Substantiation = "S1",
        DateCreated = DateTime.Today,
        LeaveStart = DateTime.Today,
        LeaveEnd = DateTime.Today,
        LeaveType = new ProposalLeaveType { Name = "PLT1", Description = "PLT1" }
    });
    db.Proposal.Add(new ProposalCustom
    {
        Substantiation = "S2",
        Name = "PC1",
        ProposalType = new ProposalCustomType { Name = "PCT1", Description = "PCT1" }
    });
    db.SaveChanges();
    
    var proposalCustoms = db.Proposal.OfType<ProposalCustom>()
        .Include(l => l.ProposalType)
        .ToList();
    
    var proposalLeaves = db.Proposal.OfType<ProposalLeave>()
        .Include(l => l.LeaveType)
        .ToList();