兩個實體中,若是一個實體的一個實例與另外一個實體相關,則咱們就叫作一對一關係數據庫
查看以下代碼:ide
public class Student { public Student() { } public int StudentId { get; set; } public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress { public int StudentAddressId { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string City { get; set; } public int Zipcode { get; set; } public string State { get; set; } public string Country { get; set; } public virtual Student Student { get; set; } }
這裏,Student類只能擁有零個或最多一個StudentAddress類,因此符合一對一關係ui
在SQL Server數據庫中,一對一關係發生在當一張表的主鍵是另外一張表的主鍵或外鍵時,因此如上代碼中,咱們要配置StudentId爲主鍵,StudentAddressId既爲主鍵也爲外鍵。spa
Student類會根據Code-First默認約定將StudentId屬性配置爲主鍵,因此這裏咱們就不用額外的配置它了。.net
StudentAddress類中,咱們須要配置StudentAddressId既爲主鍵又爲外鍵,一樣的,Code-First默認約定會將StudentAddressId配置爲主鍵,因此這裏咱們僅僅須要使用[ForeignKey("Student")]特性將StudentAddressId屬性配置爲外鍵便可。翻譯
代碼以下:code
public class Student { public Student() { } public int StudentId { get; set; } public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress { [ForeignKey("Student")] public int StudentAddressId { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string City { get; set; } public int Zipcode { get; set; } public string State { get; set; } public string Country { get; set; } public virtual Student Student { get; set; } }
這樣,Student類和StudentAddress類就配置好了一對一關係。blog
若是StudentAddressId名稱改變了,好比下面代碼,改爲了StudentId,默認就不會建立主鍵了,須要手動添加上[Key]特性:ip
public class Student { public Student() { } public int StudentId { get; set; } public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress { [Key, ForeignKey("Student")] public int StudentId { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string City { get; set; } public int Zipcode { get; set; } public string State { get; set; } public string Country { get; set; } public virtual Student Student { get; set; } }
這樣,StudentAddress類中的StudentId就被配置爲既是主鍵,又是外鍵。ci
注意: 雖然Student類中包含StudentAddress類屬性,StudentAddress類中也包含Student類屬性,但Student類的StudentAddress類屬性能夠爲空,而StudentAddress類的Student類屬性不能爲空!若是保存一個Student類屬性爲空的StudentAddress類,會拋出異常。
下面咱們將不使用任何DataAnnotations特性(雖然它們能夠一塊兒使用)僅僅使用Fluent API來配置一對一關係。
既然默認約定會自動爲Student和StudentAddress建立主鍵,因此這裏咱們僅僅須要把StudentAddressId配置爲外鍵
代碼以下:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Configure Student & StudentAddress entity modelBuilder.Entity<Student>() .HasOptional(s => s.Address) // Mark Address property optional in Student entity .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student }
上面代碼中,Student實體的Address屬性使用了HasOptional()方法,即Address屬性不是必須的,可爲空,又爲StudentAddress類的Student屬性使用了WithRequired()方法,即Student屬性爲必填,不能爲空,若是存儲StudentAddress實體的時候發現Student屬性爲空,則會拋出異常。
這樣配置之後,StudentAddressId就已是外鍵了。
以下代碼,咱們想要StudentAddress類的StudentId屬性成爲主外鍵
public class Student { public Student() { } public int StudentId { get; set; } public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress { public int StudentId { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string City { get; set; } public int Zipcode { get; set; } public string State { get; set; } public string Country { get; set; } public virtual Student Student { get; set; } }
Fluent API配置以下:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Configure StudentId as PK for StudentAddress modelBuilder.Entity<StudentAddress>() .HasKey(e => e.StudentId); // Configure StudentId as FK for StudentAddress modelBuilder.Entity<Student>() .HasOptional(s => s.Address) .WithRequired(ad => ad.Student); }
說白了,所謂的一對一關係,便是兩個實體類中做爲主外鍵的類屬性都不能爲空。
注意:一對一關係在SQL Server中並非必須,一般使用一對零或一對一。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Configure StudentId as PK for StudentAddress modelBuilder.Entity<StudentAddress>() .HasKey(e => e.StudentId); // Configure StudentId as FK for StudentAddress modelBuilder.Entity<Student>() .HasRequired(s => s.Address) .WithRequiredPrincipal(ad => ad.Student); }
在上面的代碼中, modelBuilder.Entity<Student>().HasRequired(s => s.Address)使得Student類的Address屬性爲必須,
WithRequiredPrincipal(ad => ad.Student) 方法使的StudentAddress類的Student屬性爲必須。
注意:這裏主要的實體類是Student,依賴的實體類是StudentAddress。
DataAnnotations and Fluent API都會建立以下的一對零或一對一關係的數據庫:
咱們能夠檢查Student表和StudentAddress表之間的關係:
圖表關係以下
啊啊啊啊啊,雖然最近忙成狗,可是說好的翻譯,必定會堅持下去的!!!