EF核心2.0一对多共享同一个表

时间:2017-11-22 06:16:39

标签: entity-framework entity-framework-core

如何解决"导航属性只能参与单一关系。"以下案例有错误吗?

1公司有许多Milestone和MissionValueStory,其中Milestone和MissionValueStory共享相同的表,具有不同的typeId,并且每个都有很多翻译,只与companyInfoId链接

或者更好地打破了公司信息与公司之间的关系,只是另一个获取companyInfo的查询很容易?



    public class Company
    {
        [key]
        public long Id { get; set; }

        public string Name { get; set; }

        public virtual ICollection<CompanyInfo> Milestone { get; set; } //multi

        public virtual ICollection<CompanyInfo> MissionValueStory { get; set; } //multi
    }

    public class CompanyInfo
    {
        [key]
        public long Id { get; set; }

        public long typeId { get; set; }
        
        [Required]
        public long CompanyId { get; set; }
            
        public string Title { get; set; }
        
        public string Text { get; set; }
      
        [ForeignKey("CompanyId")]
        public virtual Company Company { get; set; } 
        
        public ICollection<Translation> Translation { get; set; }
    }

    public class Translation
    {
        [key]
        public long Id { get; set; }
        
        public string Title { get; set; }
        
        [Required]
        public long CompanyInfoId { get; set; }
        
        public string Language { get; set; }
      
        [ForeignKey("CompanyInfoId")]
        public virtual CompanyInfo CompanyInfo { get; set; } 
    }

           modelBuilder.Entity<Company>()
              .HasMany(e => e.Milestone)
              .WithOne(t => t.Company)
              .HasForeignKey(m => m.CompanyId).IsRequired()
                .OnDelete(DeleteBehavior.Cascade);


            modelBuilder.Entity<Company>()
              .HasMany(e => e.MissionValueStory)
              .WithOne(t => t.Company)
              .HasForeignKey(m => m.CompanyId).IsRequired()
                .OnDelete(DeleteBehavior.Cascade);

            
            modelBuilder.Entity<CompanyInfo>()
              .HasMany(e => e.Translation)
              .WithOne(t => t.CompanyInfo).IsRequired();
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

您正在尝试做的事情是合法的不受支持。至少在你做这件事的方式上。幸运的是,这对你来说是一个相当轻松的解决方案。使用每个层次结构表。

将类CompanyInfo更改为名为CompanyInfoBase的抽象类,并将其设为抽象类型。在CompanyInfoBase上创建typeId摘要。

创建两个实现CompanyInfoBase的新类:

public class MilestoneCompanyInfo : CompanyInfoBase
{
    public override long typeId { get; set; } = MILESTONE_TYPE_ID;
}

public class MissionValueStoryCompanyInfo : CompanyInfoBase
{
    public override long typeId { get; set; } = MISSION_VALUE_STORY_TYPE_ID;
}

其中MILESTONE_TYPE_IDMISSION_VALUE_STORY_TYPE_ID是某种预定义的常量。

然后,在你的DbContext的OnModelCreating中,使用typeId作为你的鉴别器。

它看起来像这样:

modelBuilder.Entity<CompanyInfoBase>()
    .HasDiscriminator<long>(nameof(CompanyInfoBase.typeId))
    .HasValue<MilestoneCompanyInfo>(MILESTONE_TYPE_ID)
    .HasValue<MissionValueStoryCompanyInfo>(MISSION_VALUE_STORY_TYPE_ID);

由于您正在更改实体的名称,因此值得设置表名以适应您现有的数据库。类似的东西:

modelBuilder.Entity<CompanyInfoBase>().ToTable("CompanyInfos");

其他读者注意:由于他决定使用long,因此只需要定义这样的鉴别器。如果他刚刚离开它未定义,那么EF Core会自动处理这个(通过创建一个名为discriminator的列,其中包含具体的类名)。

这是指向继承参考页面的链接:https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/inheritance