public class BaseModel { public int Id { get; set; } public DateTime CreateDateTime { get; set; } } public class Address { public string Street { get; set; } public string City { get; set; } public string ZipCode { get; set; } } public class User:BaseModel { public string Name {get;set;} public string Birthdate {get;set;} public string IdNumber {get;set;} public Address Address {get;set;} }
以上代碼在ORM中稱爲組合類,EF會將這兩個類映射在一張表中。當Code First發現不能推斷出類的主鍵,而且沒有經過Data Annotations或Fluent API註冊主鍵,那麼該類型將被自動註冊爲複雜類型。數據庫
注意:
咱們接下來建立 DbContext 類函數
public class EfDbContext : DbContext { public EfDbContext() { Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EfDbContext>()); } public DbSet<User> Users { get; set; } }
建立完DbContext類後,咱們編寫將數據存入數據庫的方法:ui
using (var efDbContext = new EfDbContext()) { var user = new User() { Birthdate = DateTime.Now, CreateDateTime = DateTime.Now, Name = "張三", IdNumber = "1234567" }; efDbContext.Users.Add(user); efDbContext.SaveChanges(); }
運行上述代碼,會獲得以下錯誤:
spa
出現上述錯誤的緣由是咱們沒有初始化 Address 類,其中一個(後面我會講解另外一個解決方法)解決方法是在 new User(){} 內初始化 Address,修正後的代碼以下:code
using (var efDbContext = new EfDbContext()) { var user = new User() { Birthdate = DateTime.Now, CreateDateTime = DateTime.Now, Name = "張三", IdNumber = "1234567", Address = new Address() }; efDbContext.Users.Add(user); efDbContext.SaveChanges(); }
如今咱們按照上面所述,對咱們先前編寫的內容進行改造,這三條規則也是解決咱們前面所遇到的BUG的另外一個方法。對象
public class BaseModel { public int Id { get; set; } public DateTime CreateDateTime { get; set; } } public class Address { public string Street { get; set; } public string City { get; set; } public string ZipCode { get; set; } public bool HasValue { get { return (Street != null || ZipCode != null || City != null); } } } public class User : BaseModel { public User() { Address = new Address(); } public string Name { get; set; } public DateTime Birthdate { get; set; } public string IdNumber { get; set; } public Address Address { get; set; } } public class EfDbContext : DbContext { public EfDbContext() { Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EfDbContext>()); } public virtual void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.ComplexType<Address>(); } public DbSet<User> Users { get; set; } }
代碼改造後咱們能夠輕鬆的經過 變動追蹤API 來訪問數據的原始值和當前值。所謂原始值就是從數據庫查詢出來的值,當前值就是實體目前的值。入口點是 DbContext的Entry方法,返回對象類型是 DbEntityEntry 。咱們看一下訪問原始值和當前值得例子:ip
using (var efDbContext = new EfDbContext()) { var user = efDbContext.Users.Find(1); var oriValue = efDbContext.Entry(user).ComplexProperty(u => u.Address).OriginalValue; //將city的值改成北京 user.Address.City = "北京"; var curValue = efDbContext.Entry(user).ComplexProperty(u => u.Address).CurrentValue; Console.WriteLine("原始值:"+oriValue.City+" 當前值:"+curValue.City); Console.Read(); }
運行上述代碼,將會看到以下的輸出:
ci
一樣,咱們也能夠經過鏈式調用,獲取複雜了類型的屬性或者設置複雜類型的屬性:rem
var user = efDbContext.Users.Find(1); var city = efDbContext.Entry(user).ComplexProperty(u => u.Address).Property(a => a.City).CurrentValue; Console.Write(city);
從上面的講解咱們卡一看到,用複雜類型很雙,一直用一直爽,可是複雜類型仍是有他的限制的:get