[英]Entity Framework Code First One-to-One Required-Required Relationship
使用 Entity Framework Code First 4.3.1 時,可以創建具有 1 對 1 多重性的關系。 也就是說,關系的每一端都有一個實體。
可以將 1 對 1 關系配置為必需-必需或必需-可選^。 但是,當我在兩者之間切換時,我看不出有任何區別:
因此,盡管關系被配置為required-required ,但我能夠創建沒有相應RequiredDependentAs記錄的RequiredPrincipalAs記錄。 這似乎與HasRequired(...)的文檔相矛盾:
配置此實體類型的必需關系。 除非指定此關系,否則實體類型的實例將無法保存到數據庫中。 數據庫中的外鍵將不可為空。
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.DependentA和RequiredDependentA.PrincipalA的導航屬性。 這將導致 EF 驗證阻止上述情況。 但是,我不想這樣做,因為它還會驗證在更新現有實體時填充了導航屬性。 這意味着應用程序必須為每次更新預取關系另一端的實體。
為什么我在更改required-required和required-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 - WithRequiredPrincipal
和HasOptional - 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.