C# 实体框架继承和关系

C# 实体框架继承和关系,c#,entity-framework,inheritance,C#,Entity Framework,Inheritance,我试图先用EntityFramework6代码实现TPH继承,但继承类型的关系有问题 我的代码是 public abstract class Base... public class Inherited1 : Base { public virtual Type1 Rel { get; set; } ... public class Inherited2 : Base { public virtual Type1 Rel {get;set;} ... 因此继承的类型具有“相同”的关系。继承

我试图先用EntityFramework6代码实现TPH继承,但继承类型的关系有问题

我的代码是

public abstract class Base...

public class Inherited1 : Base
{
public virtual Type1 Rel { get; set; }
...

public class Inherited2 : Base
{
public virtual Type1 Rel {get;set;}
...
因此继承的类型具有“相同”的关系。继承本身工作正常,但我遇到的问题是,与表Type1的关系将被添加两次(逻辑…),而另一个关系是从Inherited2.Id到Type1.Id,而不是从Inherited2.Type1Id到Type1.Id,第一个关系是(正确的)

我不确定我解释这一点是否有意义,也不确定我使用了更改了类型名的部分代码示例,但我希望您能理解这一点。如果需要,请询问更多细节

我可能可以用

更新

我创建了一个Github回购示例来演示这个问题。请随时告诉我我做错了什么

尝试使用以下方法

1-如果您想要TPT

modelBuilder.Entity<Inherited1>()
            .ToTable("Inherited1s")
            .HasKey(x => x.YourKey)
            .HasRequired(x=>Type1)
            .WithMany()
            .HasForeignKey(x=>Type1Id)
            .WillCascadeOnDelete(false);

modelBuilder.Entity<Inherited2>()
            .ToTable("Inherited2s")
            .HasKey(x => x.YourKey)
            .HasRequired(x=>Type1)
            .WithMany()
            .HasForeignKey(x=>Type1Id)
            .WillCascadeOnDelete(false);
输出正确(文件表包含鉴别器字段以及两个关系,一个用于文档与容器的关系,另一个用于附件与容器的关系)

我认为更好的解决办法是:

  • 要添加具有值的类
    文件类型(Id、名称)
    文档
    ,并将其作为外键添加到
    文件
  • 文件容器
    文件
  • 验证document类型的文件中只有一条记录与同一容器

  • 希望这能帮助你

    你在用什么?流畅的API还是注解?在这两种情况下,显示一些您正在使用的代码唯一与这些关系相关的流畅API是modelBuilder.Entity().HasMany(x=>x.Inherited1).WithRequired(x=>x.Type1.WillCascadeOnDelete();我在下面的回答中添加了TPT和TPH两种情况,以供参考。我似乎已经纠正了它们之间的关系。我意外地丢失了Inherited2.Type1关系的另一端定义。所以Type1与Inherited2没有任何关联。我在那里添加了它,EF正确地生成了关系。这种设置的缺点是,由于明显的原因,我不能在两个关系上都使用Delete-on-cascade,但至少它可以工作。我将对它进行更多的测试,并确认它确实在工作。事实上,如果我在Type1类中有ICollection,关系就可以工作,但是如果我只是有public Inherited2 PropertyName{get;set;},它就不工作了。想想看。。。我正在尝试使用fluent api with.Entity().HasOptional(x=>x.Inherited2Property)。with required(x=>x.Rel);在TPH示例中,有很多。我让它像那样工作,但是如果我在类型1中有0..1呢?0..1是0..n的一个特例,其中n=1,因此可以应用相同的逻辑,但是您应该使用hasOptional,而不是HasRequired。我已经制作了一个github repo来复制和测试这些问题。如果有人有时间,他们可以在那里帮忙。我试图在readme.md中描述想要的结果和当前的问题@AnttiSimonen我查看了样本并解释了您的模型中发生的情况,同时我还提出了另一个解决方案非常感谢您的回答。这基本上解决了问题。似乎我遗漏了foreignkey字段,我仍然很难理解为什么。例如,对于不是0到多的FileContainer-Document关系,需要很多字段?我在保存数据时仍然遇到一些问题,因为EF抱怨它无法解决正确的插入顺序。我已经把一些关系放在了可选择的位置上,我仍在与其他问题作斗争。
    modelBuilder.Entity<Base>()
                .ToTable("YourTableName")
                .HasRequired(m=>m.Type1)
                .WithMany()
                .HasForeignKey(m=>m.Type1Id)
                .WillCascadeOnDelete(); // true or false as you want
    
            modelBuilder.Entity<FileContainer>()
                .HasOptional(x => x.Document)
                .WithMany()
                .HasForeignKey(t => t.DocumentId)
                .WillCascadeOnDelete(false);
    
            modelBuilder.Entity<Document>()
                .HasRequired(t => t.FileContainer)
                .WithMany()
                .HasForeignKey(t => t.FileContainerId)
                .WillCascadeOnDelete(false);
    
            modelBuilder.Entity<Attachment>()
                .HasRequired(t => t.FileContainer)
                .WithMany()
                .HasForeignKey(t => t.FileContainerAttachmentId)
                .WillCascadeOnDelete(false);