上一博客學習了下基本的約定配置,留下幾個遺漏的,這篇就是學習下遺漏一復雜類型。
一、什么是復雜類型?
書中說道:“復雜類型也可視作值類型(?)可以作為附加屬性添加到其他類。復雜類型與實體類型的區別在於復雜類型沒有其自己的鍵。它是依賴於其"宿主"類型跟蹤變化 和持久化。一個沒有Key屬性的類型,並且作為屬性映射到一個或多個類型中,Code First就會將其視作為復雜類型。Code First將預設復雜類型的屬性出現在宿主類型映射到數據庫的表中。”
說簡單一點就是,項目中有個類A,這個A,會被其他類引用到比如:實體類B 和 實體類C,但是建立數據庫的時候,我們不想為這個分割類A建立表,而是把A類中的屬性等建立到 B 和 C 映射的表中,這時候,我們管 A 叫做復雜類型。
二、復雜類型和實體類型的區別
首先還是定義兩個類Person類和IDCard類還有數據庫上下文。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity; using EFCodeFirstModels; using System.Configuration; namespace EFCodeFirstDataAccess { public class EFCodeFirstDbContext:DbContext { public EFCodeFirstDbContext() : base("MyStrConn") { } public DbSet<Person> Persons { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EFCodeFirstModels { public enum SexType { Male, Female } [Table("Person")] public class Person { [Key] public string PersonId { get; set; } //姓名 public string Name { get; set; } //性別 public SexType Sex { get; set; } //年齡 public int Age { get; set; } public IDCard Card { get; set; } public Person(string personId, string name, SexType sex, int age,IDCard card) { PersonId = personId; Name = name; Sex = sex; Age = age; Card = card; } public Person() { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace EFCodeFirstModels { public class IDCard { //法定出生日期 public DateTime BirthDate { get; set; } } }
在上面的IDCard中並沒有主鍵,這個是需要留意的,然后呢新增一個Person對象在數據庫上下文中。
using (var db=new EFCodeFirstDbContext()) { IDCard card = new IDCard(); card.BirthDate = DateTime.Now; Person p = new Person("0001","cuiyanwei",SexType.Female,25,card); db.Persons.Add(p); db.SaveChanges(); Console.WriteLine("Scueess"); }
此時會生成下面的表結構。
上面可以看到Person表中增加了一個Card_BirthDate列,但是如果在IDCard類中增加一個主鍵,結果就會不一樣。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace EFCodeFirstModels { public class IDCard { [Key] public int CardId { get; set; } //法定出生日期 public DateTime BirthDate { get; set; } } }
可以看到,數據庫中多生成了一個表。Person表中增加了一個外鍵Card_CardId.
三、復雜類型嵌套
看到這你可能會問這也沒提到復雜類型幾個字啊,哪來的復雜類型了。上面的例子中IDCard雖然也是復雜類型,由於IDCard類中屬性比較簡單,沒有嵌套這其他的類,所以EF就默認映射到Person表中了,但是假如IDCard類中有其他的類,屬於類型嵌套的話那就麻煩了。首先看下如果有嵌套不指定會怎么樣?
可以在IDCard類中增加一個屬性,用來表示出生地方的經緯度(做個比喻,不可能人出生在一個經緯度的點上,也是大致的位置)。經緯度用Location類表示。
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EFCodeFirstModels { //[ComplexType] public class Location { //經度 public double Longitude { get; set; } //緯度 public double Latitude { get; set; } } }
public class IDCard { //法定出生日期 public DateTime BirthDate { get; set; } //出生地的位置 經緯度 public Location BirthPlace { get; set; } }
同樣新增一個Person對象,此時就會報下面的錯誤。
這是為什么呢?因為系統識別不了IDCard類是復雜類型。那怎么解決呢,很簡單。只需指定IDCard是復雜類型就ok了。
[ComplexType] public class IDCard
而在Location類上並沒有指定復雜類型,這也將Location類認為是復雜類型。