2012-06-27 112 views
8

當使用實體框架代碼第一個4.3.1時,可以創建多重1對1的關係。也就是說,關係的每一端都有一個實體。實體框架代碼首先一對一所需的關係

它可以配置1對1的關係爲所需要求的需要-可選 ^。但是,當我在兩者之間切換時,我看不到任何區別:

  • 生成的數據庫架構。我的目標是SQL Server 2008.
  • EF的運行時行爲。

因此,我可以沒有相應的RequiredDependentAs紀錄創造RequiredPrincipalAs記錄,儘管關係被配置爲要求,需要。這似乎矛盾的HasRequired(...)文檔:

配置從這個實體類型的必要關係。除非指定了這種關係,否則實體類型的實例將無法保存到數據庫。數據庫中的外鍵將不可空。

http://msdn.microsoft.com/en-us/library/gg671317

時需提供-關係實體:

public class RequiredPrincipalA 
{ 
    public int Id { get; set; } 
    public virtual RequiredDependentA DependentA { get; set; } 
} 

public class RequiredDependentA 
{ 
    public int Id { get; set; } 
    public virtual RequiredPrincipalA PrincipalA { get; set; } 
} 

需要,可選關係的實體:

public class RequiredPrincipalB 
{ 
    public int Id { get; set; } 
    public virtual OptionalDependentB DependentB { get; set; } 
} 

public class OptionalDependentB 
{ 
    public int Id { get; set; } 
    public virtual RequiredPrincipalB PrincipalB { get; set; } 
} 

的的DbContext和模型的conf iguration:

public class AppContext : DbContext 
{ 
    public DbSet<RequiredPrincipalA> PrincipalAs { get; set; } 
    public DbSet<RequiredDependentA> DependentAs { get; set; } 

    public DbSet<RequiredPrincipalB> PrincipalBs { get; set; } 
    public DbSet<OptionalDependentB> DependentBs { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<RequiredPrincipalA>() 
      .HasRequired(o => o.DependentA) 
      .WithRequiredPrincipal(o => o.PrincipalA); 

     modelBuilder.Entity<RequiredPrincipalB>() 
      .HasOptional(o => o.DependentB) 
      .WithRequired(o => o.PrincipalB); 
    } 
} 

測試代碼:

Database.SetInitializer(new DropCreateDatabaseAlways<AppContext>()); 

using (var ctx = new AppContext()) 
{ 
    ctx.Database.Initialize(force: false); 

    ctx.PrincipalAs.Add(new RequiredPrincipalA()); 
    ctx.PrincipalBs.Add(new RequiredPrincipalB()); 

    ctx.SaveChanges(); 
} 

我知道我可以一個[必需]數據屬性添加到導航性能RequiredPrincipalA.DependentARequiredDependentA.PrincipalA 。這會導致EF驗證以防止上述情況。但是,我不想這樣做,因爲它還驗證更新現有實體時是否填充了導航屬性。這意味着應用程序必須預先獲取關係另一端的實體以進行每次更新。

爲什麼改變之間的關係所需要求的和必需的可選就當沒看到在EF的行爲有什麼區別?

^請注意,可選的選項也支持,但這不構成我的問題的一部分。在配置可選 - 可選關係時,生成的數據庫模式和運行時行爲有明顯區別。

回答

13

我不知道爲什麼必需允許這種情況下,但它不能存在於數據庫中,因爲關係建立在主鍵上。 Required-required表示如果相關的B不存在,則不能插入A,如果相關的A不存在則不能插入B =>既不能插入A也不能插入B.

數據庫關係一直是主體和依賴實體 - 主體始終可以不依賴而存在。

只有當A和B映射到同一個表(table splitting)時才能實現EF中的實際所需,因爲在這種情況下,它們都是用單個插入命令插入的。

+0

謝謝你的回答。這當然可以闡明我的問題的數據庫模式方面。但是,我非常想知道爲什麼EF中沒有任何明顯的行爲改變。 –

+0

是否允許需要 - 因爲它可以由EF強制運行,即使它實際上不可能在SQL中強制執行此約束? –

+0

Luke,在配置r/r和r/o時,模式沒有差別,現在可以理解,這要歸功於Ladislav的回答。現在的要點是,儘管文檔說明了什麼,但r/r似乎並沒有在運行時被EF強制執行。 –

5

不是一個真正的答案,但我有更多的話要比適合評論。但是你知道,我寫了900頁的書籍......這就是我滾動的方式。 :)

奇怪的是,我期望流暢的配置行爲與數據註釋相同的方式,我很困惑,它沒有這樣做。 (我已經把Rowan Miller連接到這個線程來獲得他的反饋)。我的意思是:在SaveChanges期間驗證約束。

在數據庫方面,我使用Ladislav。在模型中,EF使用相關實體的鍵定義1:1。但是在數據庫中,兩個表中都不能有FK,所以只有數據庫中的從屬表需要這個約束,即它的PK映射到主表中的現有PK。

最後,我明白你不想EF執行關係的原因,如果你不打算總是處理完整的圖表。我認爲1:1關係是EF關係映射中最令人困惑的事情,我總是發現自己不得不回頭提醒規則以及事情應該如何工作。