2016-09-13 174 views
2

我想实体框架6代码优先实施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第一个关系是(正确)。

我不确定我是否有意义地解释了这一点,并用部分代码示例改变了类型名称,但我希望你明白了。如果您需要任何更多的细节,请询问。

我大概可以用

UPDATE
我创建了一个示例GitHub库来演示这个问题正确地实现这一点。随时告诉我我做错了什么。 https://github.com/antsim/EntityFrameworkTester

+0

你在用什么?流利的API或注释?在这两种情况下,显示一些你正在使用的代码 – Monah

+0

与这些关系相关的唯一流畅API是 modelBuilder.Entity () .HasMany(x => x.Inherited1) .WithRequired(x => x。 Type1) .WillCascadeOnDelete(); –

+0

我在下面的答案中加入了TPT和TPH两种情况供您参考 – Monah

回答

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从文件继承和你正在使用TPH这意味着一台将与Discriminator字段创建。
  • DocumentFileContainer具有0..1类型的关系,这意味着一个外键FileContainerId应在Document因此在File
  • FileContainerAttachment创建具有类型0..N的关系,然后又空的外键将在您提供的示例中的表格文件

创建,我做了如下修改

  1. 添加FileContainerId表文件
  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); 
    

输出是正确的(文件表包含除了两个关系一个鉴别场用于容器的文件和用于与容器的附件的文件)。

在我看来,一个更好的解决方案是:

  1. 添加类FileType (Id, Name)与价值AttachmentDocument,并将其添加为File
  2. 的外键只能添加一个关系0..N FileContainerFile
  3. 之间的
  4. 要验证只有一个类型的文档的文件到同一容器中记录

希望这会帮助你

+0

在TPH示例中,您有.WithMany。我是这样工作的,但是如果我在Type1中有0..1呢? –

+0

0..1是一个0..n的特殊情况,其中n = 1,所以可以应用相同的逻辑,而不是HasRequired,您应该使用HasOptional – Monah

+0

我做了一个github repo来重现和测试这些问题。如果有人有时间,他们可以在那里帮忙。我试图在readme.md中描述想要的结果和当前的问题。 https://github.com/antsim/EntityFrameworkTester –