一對一關係
One-to-One Relationships
前言
終於講到最後一個類別之間的關聯了,要達成一對一的關係,只要在各加上References Property,就可以很簡單完成一對一關係。 如下:
[Table("Person")]
public class Person
{
[Key]
public int PersonId { get; set; }
public string Name { get; set; }
public Photo Photo { get; set; }
}
[Table("Photo")]
public class Photo
{
[Key]
public int PersonId { get; set; }
public byte[] Image { get; set; }
public string Caption { get; set; }
public Person Person { get; set; }
}
這樣設計讓Code First建立資料庫後,會發現拋出Exception
為什麼會這樣?
這是因為Person參考Photo、Photo又參考Person,Code First無法決定是誰依賴誰,意味著建立資料庫的時候不知道要把foreign key建立在Person還是Photo底下。
依照此例子的情況,我們是希望Photo依賴Person,所以要解決這個問題,要讓Code First知道Photo有foreign key,藉由此方式讓Code First知道Photo依賴Person。 如下:
[Table("Photo")]
public class Photo
{
[Key]
[ForeignKey("Person")]
public int PersonId { get; set; }
public byte[] Image { get; set; }
public string Caption { get; set; }
public Person Person { get; set; }
}
產生後的資料庫,就如我們預期的,Photo依賴Person
使用Fluent API方式
public class PhotoConfiguration : EntityTypeConfiguration<Photo>
{
public PhotoConfiguration()
{
HasRequired(p => p.Person)
.WithOptional(p => p.Photo);
}
}
或
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration()
{
HasRequired(p => p.Photo)
.WithRequiredPrincipal(p => p.Person);
}
}
Photo要是必需的
依照這種設計方式,還隱藏的另一個問題,就是新增Photo的時候一定要有Person,但是新增Person的時候不一定要有Photo。
所以如果需求上有要求新增Person的時候,也一定要有Photo,則我們要加上Required Attribute,來強制新增Person的時候一定要有Photo。 如下
[Table("Person")]
public class Person
{
[Key]
public int PersonId { get; set; }
public string Name { get; set; }
[Required]
public Photo Photo { get; set; }
}
驗證Required
using (var db = new Model1())
{
var p = new Person()
{
Name = "Miles"
};
db.Person.Add(p);
db.SaveChanges();
}
執行後Entity Framework會驗證Photo是必須的,而拋出Exception
使用Fluent API
public class PhotoConfiguration : EntityTypeConfiguration<Photo>
{
public PhotoConfiguration()
{
HasRequired(p => p.Person)
.WithRequiredDependent(p => p.Photo);
}
}
備註:使用Fluent API待確認,因為書上說明用這樣的方式可以達到Requrired,可是筆者這邊這麼try都無法成功。
一天一分享,身體好健康。
該追究的不是過去的原因,而是現在的目的。