原文鏈接:https://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx 這裡,你將學習在兩個實體間,配置一對零或者一對多的關係。 我們使用Student和 ...
這裡,你將學習在兩個實體間,配置一對零或者一對多的關係。
我們使用Student和StudentAddress實體來配置這種關係:
public class 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; }
}
你可以看這篇文章,Entity Relationship 來理解EF怎麼管理一對一、一對多、多對多關係的。
一對零或一對一的關係發生在這樣的兩個實體之間:當一個表的主鍵,是另外一個表的主鍵並且是外鍵的時候,所以我們需要配置Student實體中的StudentID屬性為主鍵,然後StudentAddressID既是主鍵又是外鍵。
使用數據註解配置一對零或一對一關係
這裡,我們將使用數據註解特性來給Student實體和StudentAddress實體,配置一對零或者一對一關係。
Student實體遵循預設的約定,它包含一個StudentId屬性,所以到時候這個屬性就會成為Students表的主鍵,Student實體我們不用作任何修改,就讓它根據預設配置就行。
對於StudentAddress實體,我們需要配置StudentAddressId為主鍵和外鍵,因為StudentAddressId遵循約定,所以只用給它配置外鍵。
public class 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導航屬性,並且StudentAddress實體包含Student導航屬性。在一對零或一對一關係中,Student可以在沒有StudentAddress的情況下被保存,但是StudentAddress沒有Student的情況下不能保存。EF將會拋出異常,如果你沒有Student實體就保存StudentAddress實體的話。
使用Fluent API配置一對零或者一對一關係
這裡我們將使用Fluent API配置一對零或者一對一關係。
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實體開始配置,HasOptional()方法配置Student實體中的Address導航屬性為可選的【保存Student實體的時候,可以沒有StudentAddress實體】,然後WithRequired方法設置StudentAddress實體中的Student導航屬性為必須的【保存StudentAddress實體的時候,必須要有Student】。上面的代碼,同樣會使StudentAddressId成為外鍵。
這樣你就配置了一對零或者一對一的關係,這裡Student可以在沒有StudentAddress的情況下保存,但是StudentAddress不能在沒有Student的情況下保存。EF API將會創建下麵的資料庫:
使用Fluent API配置一對一的關係
我們可以使用Fluent API配置一對一的關係,這樣情況下,兩個實體對於彼此都是必須的,意味著:Student必須包含StudentAddress,並且StudentAddress必須包含Student。
請註意:SQL Server中,一對一的關係,在技術上是不可能的。上面的代碼設置將會永遠是一對零或一對一關係。EF只是對實體形成一對一的關係,並不是在資料庫中是一對一關係。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// 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實體中的 StudentAddress導航類型的Address屬性是必須的,.WithRequiredPrincipal(ad => ad.Student)
是設置StudentAddress實體中的Student屬性是必須的。
使用 EF Power Tools為上面的一對一的例子創建實體對象模型,如下:
這一節,一對一的關係就講解完了,下一節學習一對多的關係。