2016-09-13 171 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 –