实体框架继承和关系

时间:2016-09-13 06:16:35

标签: c# entity-framework inheritance

我正在尝试使用Entity Framework 6 Code First实现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 repo来演示这个问题。随意告诉我我做错了什么。 https://github.com/antsim/EntityFrameworkTester

1 个答案:

答案 0 :(得分:2)

尝试使用以下

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

2 - 如果你想要TPH

modelBuilder.Entity<Base>()
            .ToTable("YourTableName")
            .HasRequired(m=>m.Type1)
            .WithMany()
            .HasForeignKey(m=>m.Type1Id)
            .WillCascadeOnDelete(); // true or false as you want

有关详细信息,请查看此article

基于您提供的样本

  • AttachmentDocument继承自File,您使用的是TPH,这意味着将使用Discriminator字段创建一个表。
  • DocumentFileContainer的关系类型为0..1,这意味着应在FileContainerId中创建外键Document,因此File } table
  • FileContainerAttachment的关系类型为0..n,然后将在表File
  • 中创建另一个可以为空的外键

在您提供的示例中,我进行了以下更改

  1. 将FileContainerId添加到表Document
  2. 将FileContainerAttachmentId添加到表附件
  3. 对TestContext所做的更改是

            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);
    
  4. 输出正确(文件表包含鉴别器字段以及两个关系,一个用于带有容器的文档,另一个用于带容器的附件)。

    我认为更好的解决方案是:

    1. 添加值为FileType ( Id, Name)Attachment的课程Document,并将其添加为File
    2. 中的外键
    3. FileContainerFile
    4. 之间仅添加一个关系0..n
    5. 验证文件类型文档中只有一条记录到同一容器
    6. 希望这会对你有所帮助