簡體   English   中英

Entity Framework Code First一對一必需關系

[英]Entity Framework Code First One-to-One Required-Required Relationship

使用 Entity Framework Code First 4.3.1 時,可以創建具有 1 對 1 多重性的關系。 也就是說,關系的每一端都有一個實體。

可以將 1 對 1 關系配置為必需-必需必需-可選^。 但是,當我在兩者之間切換時,我看不出有任何區別:

  • 生成的數據庫模式。 我的目標是 SQL Server 2008。
  • EF 的運行時行為。

因此,盡管關系被配置為required-required ,但我能夠創建沒有相應RequiredDependentAs記錄的RequiredPrincipalAs記錄。 這似乎與HasRequired(...)的文檔相矛盾:

配置此實體類型的必需關系。 除非指定此關系,否則實體類型的實例將無法保存到數據庫中。 數據庫中的外鍵將不可為空。

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

required-required關系實體:

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 和模型配置:

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

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

為什么我在更改required-requiredrequired-optional之間的關系時看不到 EF 的行為有任何差異?

^請注意,也支持 optional-optional 但這不構成我的問題的一部分。 配置可選-可選關系時,生成的數據庫模式和運行時行為存在明顯差異。

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

數據庫關系始終具有主體和依賴實體 - 主體始終可以在沒有依賴的情況下存在。

只有當 A 和 B 都映射到同一個表( 表拆分)時,才能在 EF 中實現真正的 required-required,因為在這種情況下,它們都是使用單個插入命令插入的。

不是真正的答案,但我要說的比評論要多。 但是你知道,我寫了 900 頁的書……這就是我的工作方式。 :)

奇怪的是,我希望流暢的配置與數據注釋的行為方式相同,但我很困惑它沒有這樣做。 (我已經通過此線程的鏈接向 Rowan Miller 發送了 ping,以獲取他的反饋。)我的意思是:在 SaveChanges 期間驗證約束。

在數據庫方面,我與 Ladislav 合作。在模型中,EF 使用相關實體的鍵定義 1:1。 但是在數據庫中,您不能在兩個表中都有 FK,因此只有數據庫中的從屬表需要將其 PK 映射到主表中現有 PK 的約束。

最后,如果您不打算始終處理完整圖表,我理解您不希望 EF 強制執行關系的原因。 我認為 1:1 關系是 EF 關系映射中最令人困惑的,我總是發現自己必須返回以獲取規則提醒以及事情應該如何運作。

老問題。 但由於 EF6 仍在使用,甚至可用於 .Net 標准,而且這個問題可能是一個真正的麻煩,我認為值得一提的是我在其他答案中找不到的東西。

確實, HasRequired - WithRequiredPrincipalHasOptional - WithRequired產生相同的數據庫模式和相同的運行時行為。 也就是說,對於這兩種映射,都可以在沒有依賴實體的情況下保存主體,並在以后刪除依賴實體。 HasRequired

但是有一種方法可以讓 EF在創建實體時驗證所需的關系,只需添加一個[Required]屬性即可:

public class RequiredPrincipalA
{
    public int Id { get; set; }

    [Required] // <== here
    public virtual RequiredDependentA DependentA { get; set; }
}

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

如前所述,僅在創建實體時。 仍然可以設置RequiredPrincipalA.RequiredDependentA = null並成功保存。 但我認為,幸運的是,代碼中發生這種情況的可能性遠低於忘記設置所需的依賴項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM